2002-08-12 21:17:25 +00:00
|
|
|
//===- InstructionCombining.cpp - Combine multiple instructions -----------===//
|
2005-04-21 23:48:37 +00:00
|
|
|
//
|
2003-10-20 19:43:21 +00:00
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file was developed by the LLVM research group and is distributed under
|
|
|
|
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
2005-04-21 23:48:37 +00:00
|
|
|
//
|
2003-10-20 19:43:21 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
2001-12-14 16:52:21 +00:00
|
|
|
//
|
|
|
|
// InstructionCombining - Combine instructions to form fewer, simple
|
2002-09-02 04:59:56 +00:00
|
|
|
// instructions. This pass does not modify the CFG This pass is where algebraic
|
|
|
|
// simplification happens.
|
2001-12-14 16:52:21 +00:00
|
|
|
//
|
|
|
|
// This pass combines things like:
|
2004-05-04 15:19:33 +00:00
|
|
|
// %Y = add int %X, 1
|
|
|
|
// %Z = add int %Y, 1
|
2001-12-14 16:52:21 +00:00
|
|
|
// into:
|
2004-05-04 15:19:33 +00:00
|
|
|
// %Z = add int %X, 2
|
2001-12-14 16:52:21 +00:00
|
|
|
//
|
|
|
|
// This is a simple worklist driven algorithm.
|
|
|
|
//
|
2003-09-10 05:29:43 +00:00
|
|
|
// This pass guarantees that the following canonicalizations are performed on
|
2003-07-23 21:41:57 +00:00
|
|
|
// the program:
|
|
|
|
// 1. If a binary operator has a constant operand, it is moved to the RHS
|
2003-08-12 21:53:41 +00:00
|
|
|
// 2. Bitwise operators with constant operands are always grouped so that
|
|
|
|
// shifts are performed first, then or's, then and's, then xor's.
|
2003-07-23 21:41:57 +00:00
|
|
|
// 3. SetCC instructions are converted from <,>,<=,>= to ==,!= if possible
|
|
|
|
// 4. All SetCC instructions on boolean values are replaced with logical ops
|
2003-08-13 04:18:28 +00:00
|
|
|
// 5. add X, X is represented as (X*2) => (X << 1)
|
|
|
|
// 6. Multiplies with a power-of-two constant argument are transformed into
|
|
|
|
// shifts.
|
2004-11-14 19:13:23 +00:00
|
|
|
// ... etc.
|
2003-07-23 21:41:57 +00:00
|
|
|
//
|
2001-12-14 16:52:21 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2004-03-13 23:54:27 +00:00
|
|
|
#define DEBUG_TYPE "instcombine"
|
2002-05-07 20:03:00 +00:00
|
|
|
#include "llvm/Transforms/Scalar.h"
|
2004-10-12 04:52:52 +00:00
|
|
|
#include "llvm/IntrinsicInst.h"
|
2002-02-26 21:46:54 +00:00
|
|
|
#include "llvm/Pass.h"
|
2002-11-04 16:18:53 +00:00
|
|
|
#include "llvm/DerivedTypes.h"
|
2003-06-26 05:06:25 +00:00
|
|
|
#include "llvm/GlobalVariable.h"
|
2003-11-02 05:57:39 +00:00
|
|
|
#include "llvm/Target/TargetData.h"
|
|
|
|
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
|
|
|
|
#include "llvm/Transforms/Utils/Local.h"
|
2004-04-05 01:30:19 +00:00
|
|
|
#include "llvm/Support/CallSite.h"
|
2004-12-08 23:43:58 +00:00
|
|
|
#include "llvm/Support/Debug.h"
|
2004-04-05 01:30:19 +00:00
|
|
|
#include "llvm/Support/GetElementPtrTypeIterator.h"
|
2002-04-18 17:39:14 +00:00
|
|
|
#include "llvm/Support/InstVisitor.h"
|
2005-08-02 19:16:58 +00:00
|
|
|
#include "llvm/Support/MathExtras.h"
|
2004-07-30 07:50:03 +00:00
|
|
|
#include "llvm/Support/PatternMatch.h"
|
2004-09-01 22:55:40 +00:00
|
|
|
#include "llvm/ADT/Statistic.h"
|
2004-12-08 23:43:58 +00:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2002-05-14 15:24:07 +00:00
|
|
|
#include <algorithm>
|
2006-01-22 23:32:06 +00:00
|
|
|
#include <iostream>
|
2003-12-07 01:24:23 +00:00
|
|
|
using namespace llvm;
|
2004-07-30 07:50:03 +00:00
|
|
|
using namespace llvm::PatternMatch;
|
2003-11-11 22:41:34 +00:00
|
|
|
|
2002-04-18 17:39:14 +00:00
|
|
|
namespace {
|
2002-10-01 22:38:41 +00:00
|
|
|
Statistic<> NumCombined ("instcombine", "Number of insts combined");
|
|
|
|
Statistic<> NumConstProp("instcombine", "Number of constant folds");
|
|
|
|
Statistic<> NumDeadInst ("instcombine", "Number of dead inst eliminated");
|
Use EraseInstFromFunction in a few cases to put the uses of the removed
instruction onto the worklist (in case they are now dead).
Add a really trivial local DSE implementation to help out bitfield code.
We now fold this:
struct S {
unsigned char a : 1, b : 1, c : 1, d : 2, e : 3;
S();
};
S::S() : a(0), b(0), c(1), d(0), e(6) {}
to this:
void %_ZN1SC1Ev(%struct.S* %this) {
entry:
%tmp.1 = getelementptr %struct.S* %this, int 0, uint 0
store ubyte 38, ubyte* %tmp.1
ret void
}
much earlier (in gccas instead of only in gccld after DSE runs).
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@26050 91177308-0d34-0410-b5e6-96231b3b80d8
2006-02-08 03:25:32 +00:00
|
|
|
Statistic<> NumDeadStore("instcombine", "Number of dead stores eliminated");
|
2004-12-08 23:43:58 +00:00
|
|
|
Statistic<> NumSunkInst ("instcombine", "Number of instructions sunk");
|
2002-10-01 22:38:41 +00:00
|
|
|
|
2002-04-27 06:56:12 +00:00
|
|
|
class InstCombiner : public FunctionPass,
|
2002-04-18 17:39:14 +00:00
|
|
|
public InstVisitor<InstCombiner, Instruction*> {
|
|
|
|
// Worklist of all of the instructions that need to be simplified.
|
|
|
|
std::vector<Instruction*> WorkList;
|
2003-11-02 05:57:39 +00:00
|
|
|
TargetData *TD;
|
2002-04-18 17:39:14 +00:00
|
|
|
|
2004-02-28 05:22:00 +00:00
|
|
|
/// AddUsersToWorkList - When an instruction is simplified, add all users of
|
|
|
|
/// the instruction to the work lists because they might get more simplified
|
|
|
|
/// now.
|
|
|
|
///
|
2006-02-07 06:56:34 +00:00
|
|
|
void AddUsersToWorkList(Value &I) {
|
2002-06-25 16:13:24 +00:00
|
|
|
for (Value::use_iterator UI = I.use_begin(), UE = I.use_end();
|
2002-04-18 17:39:14 +00:00
|
|
|
UI != UE; ++UI)
|
|
|
|
WorkList.push_back(cast<Instruction>(*UI));
|
|
|
|
}
|
|
|
|
|
2004-02-28 05:22:00 +00:00
|
|
|
/// AddUsesToWorkList - When an instruction is simplified, add operands to
|
|
|
|
/// the work lists because they might get more simplified now.
|
|
|
|
///
|
|
|
|
void AddUsesToWorkList(Instruction &I) {
|
|
|
|
for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i)
|
|
|
|
if (Instruction *Op = dyn_cast<Instruction>(I.getOperand(i)))
|
|
|
|
WorkList.push_back(Op);
|
|
|
|
}
|
|
|
|
|
2002-09-02 04:59:56 +00:00
|
|
|
// removeFromWorkList - remove all instances of I from the worklist.
|
|
|
|
void removeFromWorkList(Instruction *I);
|
2002-04-18 17:39:14 +00:00
|
|
|
public:
|
2002-06-25 16:13:24 +00:00
|
|
|
virtual bool runOnFunction(Function &F);
|
2002-04-18 17:39:14 +00:00
|
|
|
|
2002-04-28 21:27:06 +00:00
|
|
|
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
2003-11-02 05:57:39 +00:00
|
|
|
AU.addRequired<TargetData>();
|
2002-10-21 20:00:28 +00:00
|
|
|
AU.setPreservesCFG();
|
2002-04-28 21:27:06 +00:00
|
|
|
}
|
|
|
|
|
2004-04-05 01:30:19 +00:00
|
|
|
TargetData &getTargetData() const { return *TD; }
|
|
|
|
|
2002-04-18 17:39:14 +00:00
|
|
|
// Visitation implementation - Implement instruction combining for different
|
|
|
|
// instruction types. The semantics are as follows:
|
|
|
|
// Return Value:
|
|
|
|
// null - No change was made
|
2002-08-12 21:17:25 +00:00
|
|
|
// I - Change was made, I is still valid, I may be dead though
|
2002-04-18 17:39:14 +00:00
|
|
|
// otherwise - Change was made, replace I with returned instruction
|
2005-04-21 23:48:37 +00:00
|
|
|
//
|
2002-06-25 16:13:24 +00:00
|
|
|
Instruction *visitAdd(BinaryOperator &I);
|
|
|
|
Instruction *visitSub(BinaryOperator &I);
|
|
|
|
Instruction *visitMul(BinaryOperator &I);
|
|
|
|
Instruction *visitDiv(BinaryOperator &I);
|
|
|
|
Instruction *visitRem(BinaryOperator &I);
|
|
|
|
Instruction *visitAnd(BinaryOperator &I);
|
|
|
|
Instruction *visitOr (BinaryOperator &I);
|
|
|
|
Instruction *visitXor(BinaryOperator &I);
|
2005-04-24 06:59:08 +00:00
|
|
|
Instruction *visitSetCondInst(SetCondInst &I);
|
|
|
|
Instruction *visitSetCondInstWithCastAndCast(SetCondInst &SCI);
|
|
|
|
|
2005-01-13 20:14:25 +00:00
|
|
|
Instruction *FoldGEPSetCC(User *GEPLHS, Value *RHS,
|
|
|
|
Instruction::BinaryOps Cond, Instruction &I);
|
2003-03-10 19:16:08 +00:00
|
|
|
Instruction *visitShiftInst(ShiftInst &I);
|
2006-01-06 07:12:35 +00:00
|
|
|
Instruction *FoldShiftByConstant(Value *Op0, ConstantUInt *Op1,
|
|
|
|
ShiftInst &I);
|
2002-06-25 16:13:24 +00:00
|
|
|
Instruction *visitCastInst(CastInst &CI);
|
2005-01-19 21:50:18 +00:00
|
|
|
Instruction *FoldSelectOpOp(SelectInst &SI, Instruction *TI,
|
|
|
|
Instruction *FI);
|
2004-03-12 05:52:32 +00:00
|
|
|
Instruction *visitSelectInst(SelectInst &CI);
|
2003-06-19 17:00:31 +00:00
|
|
|
Instruction *visitCallInst(CallInst &CI);
|
|
|
|
Instruction *visitInvokeInst(InvokeInst &II);
|
2002-06-25 16:13:24 +00:00
|
|
|
Instruction *visitPHINode(PHINode &PN);
|
|
|
|
Instruction *visitGetElementPtrInst(GetElementPtrInst &GEP);
|
2002-11-04 16:18:53 +00:00
|
|
|
Instruction *visitAllocationInst(AllocationInst &AI);
|
2003-12-07 01:24:23 +00:00
|
|
|
Instruction *visitFreeInst(FreeInst &FI);
|
2003-06-26 05:06:25 +00:00
|
|
|
Instruction *visitLoadInst(LoadInst &LI);
|
2005-01-31 05:36:43 +00:00
|
|
|
Instruction *visitStoreInst(StoreInst &SI);
|
2003-06-04 04:46:00 +00:00
|
|
|
Instruction *visitBranchInst(BranchInst &BI);
|
2004-07-03 00:26:11 +00:00
|
|
|
Instruction *visitSwitchInst(SwitchInst &SI);
|
2006-04-15 01:39:45 +00:00
|
|
|
Instruction *visitInsertElementInst(InsertElementInst &IE);
|
2006-01-13 22:48:06 +00:00
|
|
|
Instruction *visitExtractElementInst(ExtractElementInst &EI);
|
2006-04-10 22:45:52 +00:00
|
|
|
Instruction *visitShuffleVectorInst(ShuffleVectorInst &SVI);
|
2002-04-18 17:39:14 +00:00
|
|
|
|
|
|
|
// visitInstruction - Specify what to return for unhandled instructions...
|
2002-06-25 16:13:24 +00:00
|
|
|
Instruction *visitInstruction(Instruction &I) { return 0; }
|
2002-08-09 23:47:40 +00:00
|
|
|
|
2003-06-19 17:00:31 +00:00
|
|
|
private:
|
2003-10-07 22:32:43 +00:00
|
|
|
Instruction *visitCallSite(CallSite CS);
|
2003-06-19 17:00:31 +00:00
|
|
|
bool transformConstExprCastCall(CallSite CS);
|
|
|
|
|
2004-04-05 01:30:19 +00:00
|
|
|
public:
|
2002-08-09 23:47:40 +00:00
|
|
|
// InsertNewInstBefore - insert an instruction New before instruction Old
|
|
|
|
// in the program. Add the new instruction to the worklist.
|
|
|
|
//
|
Fold (and (setcc X, C1), (setcc X, C2))
This is important for several reasons:
1. Benchmarks have lots of code that looks like this (perlbmk in particular):
%tmp.2.i = setne int %tmp.0.i, 128 ; <bool> [#uses=1]
%tmp.6343 = seteq int %tmp.0.i, 1 ; <bool> [#uses=1]
%tmp.63 = and bool %tmp.2.i, %tmp.6343 ; <bool> [#uses=1]
we now fold away the setne, a clear improvement.
2. In the more important cases, such as (X >= 10) & (X < 20), we now produce
smaller code: (X-10) < 10.
3. Perhaps the nicest effect of this patch is that it really helps out the
code generators. In particular, for a 'range test' like the above,
instead of generating this on X86 (the difference on PPC is even more
pronounced):
cmp %EAX, 50
setge %CL
cmp %EAX, 100
setl %AL
and %CL, %AL
cmp %CL, 0
we now generate this:
add %EAX, -50
cmp %EAX, 50
Furthermore, this causes setcc's to be folded into branches more often.
These combinations trigger dozens of times in the spec benchmarks, particularly
in 176.gcc, 186.crafty, 253.perlbmk, 254.gap, & 099.go.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16559 91177308-0d34-0410-b5e6-96231b3b80d8
2004-09-28 21:48:02 +00:00
|
|
|
Instruction *InsertNewInstBefore(Instruction *New, Instruction &Old) {
|
2002-08-23 18:32:43 +00:00
|
|
|
assert(New && New->getParent() == 0 &&
|
|
|
|
"New instruction already inserted into a basic block!");
|
2002-08-09 23:47:40 +00:00
|
|
|
BasicBlock *BB = Old.getParent();
|
|
|
|
BB->getInstList().insert(&Old, New); // Insert inst
|
|
|
|
WorkList.push_back(New); // Add to worklist
|
2004-02-23 06:38:22 +00:00
|
|
|
return New;
|
2002-08-09 23:47:40 +00:00
|
|
|
}
|
|
|
|
|
2004-09-24 15:21:34 +00:00
|
|
|
/// InsertCastBefore - Insert a cast of V to TY before the instruction POS.
|
|
|
|
/// This also adds the cast to the worklist. Finally, this returns the
|
|
|
|
/// cast.
|
|
|
|
Value *InsertCastBefore(Value *V, const Type *Ty, Instruction &Pos) {
|
|
|
|
if (V->getType() == Ty) return V;
|
2005-04-21 23:48:37 +00:00
|
|
|
|
Lower vperm(x,y, mask) -> shuffle(x,y,mask) if mask is constant. This allows
us to compile oh-so-realistic stuff like this:
vec_vperm(A, B, (vector unsigned char){14});
to:
vspltb v0, v0, 14
instead of:
vspltisb v0, 14
vperm v0, v2, v1, v0
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@27452 91177308-0d34-0410-b5e6-96231b3b80d8
2006-04-06 19:19:17 +00:00
|
|
|
if (Constant *CV = dyn_cast<Constant>(V))
|
|
|
|
return ConstantExpr::getCast(CV, Ty);
|
|
|
|
|
2004-09-24 15:21:34 +00:00
|
|
|
Instruction *C = new CastInst(V, Ty, V->getName(), &Pos);
|
|
|
|
WorkList.push_back(C);
|
|
|
|
return C;
|
|
|
|
}
|
|
|
|
|
2002-08-09 23:47:40 +00:00
|
|
|
// ReplaceInstUsesWith - This method is to be used when an instruction is
|
|
|
|
// found to be dead, replacable with another preexisting expression. Here
|
|
|
|
// we add all uses of I to the worklist, replace all uses of I with the new
|
|
|
|
// value, then return I, so that the inst combiner will know that I was
|
|
|
|
// modified.
|
|
|
|
//
|
|
|
|
Instruction *ReplaceInstUsesWith(Instruction &I, Value *V) {
|
2004-02-28 05:22:00 +00:00
|
|
|
AddUsersToWorkList(I); // Add all modified instrs to worklist
|
2004-04-05 02:10:19 +00:00
|
|
|
if (&I != V) {
|
|
|
|
I.replaceAllUsesWith(V);
|
|
|
|
return &I;
|
|
|
|
} else {
|
|
|
|
// If we are replacing the instruction with itself, this must be in a
|
|
|
|
// segment of unreachable code, so just clobber the instruction.
|
2004-10-18 02:59:09 +00:00
|
|
|
I.replaceAllUsesWith(UndefValue::get(I.getType()));
|
2004-04-05 02:10:19 +00:00
|
|
|
return &I;
|
|
|
|
}
|
2002-08-09 23:47:40 +00:00
|
|
|
}
|
2004-02-28 05:22:00 +00:00
|
|
|
|
2006-02-07 06:56:34 +00:00
|
|
|
// UpdateValueUsesWith - This method is to be used when an value is
|
|
|
|
// found to be replacable with another preexisting expression or was
|
|
|
|
// updated. Here we add all uses of I to the worklist, replace all uses of
|
|
|
|
// I with the new value (unless the instruction was just updated), then
|
|
|
|
// return true, so that the inst combiner will know that I was modified.
|
|
|
|
//
|
|
|
|
bool UpdateValueUsesWith(Value *Old, Value *New) {
|
|
|
|
AddUsersToWorkList(*Old); // Add all modified instrs to worklist
|
|
|
|
if (Old != New)
|
|
|
|
Old->replaceAllUsesWith(New);
|
|
|
|
if (Instruction *I = dyn_cast<Instruction>(Old))
|
|
|
|
WorkList.push_back(I);
|
2006-02-12 08:02:11 +00:00
|
|
|
if (Instruction *I = dyn_cast<Instruction>(New))
|
|
|
|
WorkList.push_back(I);
|
2006-02-07 06:56:34 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2004-02-28 05:22:00 +00:00
|
|
|
// EraseInstFromFunction - When dealing with an instruction that has side
|
|
|
|
// effects or produces a void value, we can't rely on DCE to delete the
|
|
|
|
// instruction. Instead, visit methods should return the value returned by
|
|
|
|
// this function.
|
|
|
|
Instruction *EraseInstFromFunction(Instruction &I) {
|
|
|
|
assert(I.use_empty() && "Cannot erase instruction that is used!");
|
|
|
|
AddUsesToWorkList(I);
|
|
|
|
removeFromWorkList(&I);
|
2004-11-18 21:41:39 +00:00
|
|
|
I.eraseFromParent();
|
2004-02-28 05:22:00 +00:00
|
|
|
return 0; // Don't do anything with FI
|
|
|
|
}
|
|
|
|
|
2003-08-13 20:16:26 +00:00
|
|
|
private:
|
2003-07-24 17:35:25 +00:00
|
|
|
/// InsertOperandCastBefore - This inserts a cast of V to DestTy before the
|
|
|
|
/// InsertBefore instruction. This is specialized a bit to avoid inserting
|
|
|
|
/// casts that are known to not do anything...
|
|
|
|
///
|
|
|
|
Value *InsertOperandCastBefore(Value *V, const Type *DestTy,
|
|
|
|
Instruction *InsertBefore);
|
|
|
|
|
2003-03-11 00:12:48 +00:00
|
|
|
// SimplifyCommutative - This performs a few simplifications for commutative
|
Fold binary expressions and casts into PHI nodes that have all constant inputs.
This takes something like this:
%A = phi int [ 3, %cond_false.0 ], [ 2, %endif.0.i ], [ 2, %endif.1.i ]
%B = div int %tmp.243, 4
and turns it into:
%A = phi int [ 3/4, %cond_false.0 ], [ 2/4, %endif.0.i ], [ 2/4, %endif.1.i ]
which is later simplified (in this case) into %A = 0.
This triggers thousands of times in spec, for example, 269 times in 176.gcc.
This is tested by InstCombine/add.ll:test23 and set.ll:test18.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16582 91177308-0d34-0410-b5e6-96231b3b80d8
2004-09-29 05:07:12 +00:00
|
|
|
// operators.
|
2003-03-11 00:12:48 +00:00
|
|
|
bool SimplifyCommutative(BinaryOperator &I);
|
2003-09-19 17:17:26 +00:00
|
|
|
|
2006-02-11 09:31:47 +00:00
|
|
|
bool SimplifyDemandedBits(Value *V, uint64_t Mask,
|
|
|
|
uint64_t &KnownZero, uint64_t &KnownOne,
|
|
|
|
unsigned Depth = 0);
|
Fold binary expressions and casts into PHI nodes that have all constant inputs.
This takes something like this:
%A = phi int [ 3, %cond_false.0 ], [ 2, %endif.0.i ], [ 2, %endif.1.i ]
%B = div int %tmp.243, 4
and turns it into:
%A = phi int [ 3/4, %cond_false.0 ], [ 2/4, %endif.0.i ], [ 2/4, %endif.1.i ]
which is later simplified (in this case) into %A = 0.
This triggers thousands of times in spec, for example, 269 times in 176.gcc.
This is tested by InstCombine/add.ll:test23 and set.ll:test18.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16582 91177308-0d34-0410-b5e6-96231b3b80d8
2004-09-29 05:07:12 +00:00
|
|
|
|
|
|
|
// FoldOpIntoPhi - Given a binary operator or cast instruction which has a
|
|
|
|
// PHI node as operand #0, see if we can fold the instruction into the PHI
|
|
|
|
// (which is only possible if all operands to the PHI are constants).
|
|
|
|
Instruction *FoldOpIntoPhi(Instruction &I);
|
|
|
|
|
2004-11-14 19:13:23 +00:00
|
|
|
// FoldPHIArgOpIntoPHI - If all operands to a PHI node are the same "unary"
|
|
|
|
// operator and they all are only used by the PHI, PHI together their
|
|
|
|
// inputs, and do the operation once, to the result of the PHI.
|
|
|
|
Instruction *FoldPHIArgOpIntoPHI(PHINode &PN);
|
|
|
|
|
2003-09-19 17:17:26 +00:00
|
|
|
Instruction *OptAndOp(Instruction *Op, ConstantIntegral *OpRHS,
|
|
|
|
ConstantIntegral *AndRHS, BinaryOperator &TheAnd);
|
Implement add.ll:test29. Codegening:
struct S { unsigned int i : 6, j : 11, k : 15; } b;
void plus1 (unsigned int x) {
b.i += x;
}
as:
_plus1:
lis r2, ha16(L_b$non_lazy_ptr)
lwz r2, lo16(L_b$non_lazy_ptr)(r2)
lwz r4, 0(r2)
add r3, r4, r3
rlwimi r3, r4, 0, 0, 25
stw r3, 0(r2)
blr
instead of:
_plus1:
lis r2, ha16(L_b$non_lazy_ptr)
lwz r2, lo16(L_b$non_lazy_ptr)(r2)
lwz r4, 0(r2)
rlwinm r5, r4, 0, 26, 31
add r3, r5, r3
rlwimi r3, r4, 0, 0, 25
stw r3, 0(r2)
blr
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23379 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-18 04:24:45 +00:00
|
|
|
|
|
|
|
Value *FoldLogicalPlusAnd(Value *LHS, Value *RHS, ConstantIntegral *Mask,
|
|
|
|
bool isSub, Instruction &I);
|
2004-09-29 17:40:11 +00:00
|
|
|
Instruction *InsertRangeTest(Value *V, Constant *Lo, Constant *Hi,
|
|
|
|
bool Inside, Instruction &IB);
|
2005-10-24 06:03:58 +00:00
|
|
|
Instruction *PromoteCastOfAllocation(CastInst &CI, AllocationInst &AI);
|
Implement simple promotion for cast elimination in instcombine. This is
currently very limited, but can be extended in the future. For example,
we now compile:
uint %test30(uint %c1) {
%c2 = cast uint %c1 to ubyte
%c3 = xor ubyte %c2, 1
%c4 = cast ubyte %c3 to uint
ret uint %c4
}
to:
_xor:
movzbl 4(%esp), %eax
xorl $1, %eax
ret
instead of:
_xor:
movb $1, %al
xorb 4(%esp), %al
movzbl %al, %eax
ret
More impressively, we now compile:
struct B { unsigned bit : 1; };
void xor(struct B *b) { b->bit = b->bit ^ 1; }
To (X86/PPC):
_xor:
movl 4(%esp), %eax
xorl $-2147483648, (%eax)
ret
_xor:
lwz r2, 0(r3)
xoris r2, r2, 32768
stw r2, 0(r3)
blr
instead of (X86/PPC):
_xor:
movl 4(%esp), %eax
movl (%eax), %ecx
movl %ecx, %edx
shrl $31, %edx
# TRUNCATE movb %dl, %dl
xorb $1, %dl
movzbl %dl, %edx
andl $2147483647, %ecx
shll $31, %edx
orl %ecx, %edx
movl %edx, (%eax)
ret
_xor:
lwz r2, 0(r3)
srwi r4, r2, 31
xori r4, r4, 1
rlwimi r2, r4, 31, 0, 0
stw r2, 0(r3)
blr
This implements InstCombine/cast.ll:test30.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@28273 91177308-0d34-0410-b5e6-96231b3b80d8
2006-05-13 02:06:03 +00:00
|
|
|
|
|
|
|
Value *EvaluateInDifferentType(Value *V, const Type *Ty);
|
2002-04-18 17:39:14 +00:00
|
|
|
};
|
2002-07-23 18:06:35 +00:00
|
|
|
|
2002-07-26 21:12:46 +00:00
|
|
|
RegisterOpt<InstCombiner> X("instcombine", "Combine redundant instructions");
|
2002-04-18 17:39:14 +00:00
|
|
|
}
|
|
|
|
|
2003-03-10 21:43:22 +00:00
|
|
|
// getComplexity: Assign a complexity or rank value to LLVM Values...
|
2004-10-16 18:11:37 +00:00
|
|
|
// 0 -> undef, 1 -> Const, 2 -> Other, 3 -> Arg, 3 -> Unary, 4 -> OtherInst
|
2003-03-10 21:43:22 +00:00
|
|
|
static unsigned getComplexity(Value *V) {
|
|
|
|
if (isa<Instruction>(V)) {
|
|
|
|
if (BinaryOperator::isNeg(V) || BinaryOperator::isNot(V))
|
2004-10-16 18:11:37 +00:00
|
|
|
return 3;
|
|
|
|
return 4;
|
2003-03-10 21:43:22 +00:00
|
|
|
}
|
2004-10-16 18:11:37 +00:00
|
|
|
if (isa<Argument>(V)) return 3;
|
|
|
|
return isa<Constant>(V) ? (isa<UndefValue>(V) ? 0 : 1) : 2;
|
2003-03-10 21:43:22 +00:00
|
|
|
}
|
2002-04-18 17:39:14 +00:00
|
|
|
|
2003-03-11 00:12:48 +00:00
|
|
|
// isOnlyUse - Return true if this instruction will be deleted if we stop using
|
|
|
|
// it.
|
|
|
|
static bool isOnlyUse(Value *V) {
|
2003-10-15 16:48:29 +00:00
|
|
|
return V->hasOneUse() || isa<Constant>(V);
|
2003-03-11 00:12:48 +00:00
|
|
|
}
|
|
|
|
|
2004-02-23 06:38:22 +00:00
|
|
|
// getPromotedType - Return the specified type promoted as it would be to pass
|
|
|
|
// though a va_arg area...
|
|
|
|
static const Type *getPromotedType(const Type *Ty) {
|
2004-06-17 18:16:02 +00:00
|
|
|
switch (Ty->getTypeID()) {
|
2004-02-23 06:38:22 +00:00
|
|
|
case Type::SByteTyID:
|
|
|
|
case Type::ShortTyID: return Type::IntTy;
|
|
|
|
case Type::UByteTyID:
|
|
|
|
case Type::UShortTyID: return Type::UIntTy;
|
|
|
|
case Type::FloatTyID: return Type::DoubleTy;
|
|
|
|
default: return Ty;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-09-13 00:40:14 +00:00
|
|
|
/// isCast - If the specified operand is a CastInst or a constant expr cast,
|
|
|
|
/// return the operand value, otherwise return null.
|
|
|
|
static Value *isCast(Value *V) {
|
|
|
|
if (CastInst *I = dyn_cast<CastInst>(V))
|
|
|
|
return I->getOperand(0);
|
|
|
|
else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V))
|
|
|
|
if (CE->getOpcode() == Instruction::Cast)
|
|
|
|
return CE->getOperand(0);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-05-06 09:00:16 +00:00
|
|
|
enum CastType {
|
|
|
|
Noop = 0,
|
|
|
|
Truncate = 1,
|
|
|
|
Signext = 2,
|
|
|
|
Zeroext = 3
|
|
|
|
};
|
|
|
|
|
|
|
|
/// getCastType - In the future, we will split the cast instruction into these
|
|
|
|
/// various types. Until then, we have to do the analysis here.
|
|
|
|
static CastType getCastType(const Type *Src, const Type *Dest) {
|
|
|
|
assert(Src->isIntegral() && Dest->isIntegral() &&
|
|
|
|
"Only works on integral types!");
|
|
|
|
unsigned SrcSize = Src->getPrimitiveSizeInBits();
|
|
|
|
unsigned DestSize = Dest->getPrimitiveSizeInBits();
|
|
|
|
|
|
|
|
if (SrcSize == DestSize) return Noop;
|
|
|
|
if (SrcSize > DestSize) return Truncate;
|
|
|
|
if (Src->isSigned()) return Signext;
|
|
|
|
return Zeroext;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// isEliminableCastOfCast - Return true if it is valid to eliminate the CI
|
|
|
|
// instruction.
|
|
|
|
//
|
|
|
|
static bool isEliminableCastOfCast(const Type *SrcTy, const Type *MidTy,
|
|
|
|
const Type *DstTy, TargetData *TD) {
|
|
|
|
|
|
|
|
// It is legal to eliminate the instruction if casting A->B->A if the sizes
|
|
|
|
// are identical and the bits don't get reinterpreted (for example
|
|
|
|
// int->float->int would not be allowed).
|
|
|
|
if (SrcTy == DstTy && SrcTy->isLosslesslyConvertibleTo(MidTy))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// If we are casting between pointer and integer types, treat pointers as
|
|
|
|
// integers of the appropriate size for the code below.
|
|
|
|
if (isa<PointerType>(SrcTy)) SrcTy = TD->getIntPtrType();
|
|
|
|
if (isa<PointerType>(MidTy)) MidTy = TD->getIntPtrType();
|
|
|
|
if (isa<PointerType>(DstTy)) DstTy = TD->getIntPtrType();
|
|
|
|
|
|
|
|
// Allow free casting and conversion of sizes as long as the sign doesn't
|
|
|
|
// change...
|
|
|
|
if (SrcTy->isIntegral() && MidTy->isIntegral() && DstTy->isIntegral()) {
|
|
|
|
CastType FirstCast = getCastType(SrcTy, MidTy);
|
|
|
|
CastType SecondCast = getCastType(MidTy, DstTy);
|
|
|
|
|
|
|
|
// Capture the effect of these two casts. If the result is a legal cast,
|
|
|
|
// the CastType is stored here, otherwise a special code is used.
|
|
|
|
static const unsigned CastResult[] = {
|
|
|
|
// First cast is noop
|
|
|
|
0, 1, 2, 3,
|
|
|
|
// First cast is a truncate
|
|
|
|
1, 1, 4, 4, // trunc->extend is not safe to eliminate
|
|
|
|
// First cast is a sign ext
|
|
|
|
2, 5, 2, 4, // signext->zeroext never ok
|
|
|
|
// First cast is a zero ext
|
|
|
|
3, 5, 3, 3,
|
|
|
|
};
|
|
|
|
|
|
|
|
unsigned Result = CastResult[FirstCast*4+SecondCast];
|
|
|
|
switch (Result) {
|
|
|
|
default: assert(0 && "Illegal table value!");
|
|
|
|
case 0:
|
|
|
|
case 1:
|
|
|
|
case 2:
|
|
|
|
case 3:
|
|
|
|
// FIXME: in the future, when LLVM has explicit sign/zeroextends and
|
|
|
|
// truncates, we could eliminate more casts.
|
|
|
|
return (unsigned)getCastType(SrcTy, DstTy) == Result;
|
|
|
|
case 4:
|
|
|
|
return false; // Not possible to eliminate this here.
|
|
|
|
case 5:
|
|
|
|
// Sign or zero extend followed by truncate is always ok if the result
|
|
|
|
// is a truncate or noop.
|
|
|
|
CastType ResultCast = getCastType(SrcTy, DstTy);
|
|
|
|
if (ResultCast == Noop || ResultCast == Truncate)
|
|
|
|
return true;
|
|
|
|
// Otherwise we are still growing the value, we are only safe if the
|
|
|
|
// result will match the sign/zeroextendness of the result.
|
|
|
|
return ResultCast == FirstCast;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If this is a cast from 'float -> double -> integer', cast from
|
|
|
|
// 'float -> integer' directly, as the value isn't changed by the
|
|
|
|
// float->double conversion.
|
|
|
|
if (SrcTy->isFloatingPoint() && MidTy->isFloatingPoint() &&
|
|
|
|
DstTy->isIntegral() &&
|
|
|
|
SrcTy->getPrimitiveSize() < MidTy->getPrimitiveSize())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// Packed type conversions don't modify bits.
|
|
|
|
if (isa<PackedType>(SrcTy) && isa<PackedType>(MidTy) &&isa<PackedType>(DstTy))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// ValueRequiresCast - Return true if the cast from "V to Ty" actually results
|
|
|
|
/// in any code being generated. It does not require codegen if V is simple
|
|
|
|
/// enough or if the cast can be folded into other casts.
|
|
|
|
static bool ValueRequiresCast(const Value *V, const Type *Ty, TargetData *TD) {
|
|
|
|
if (V->getType() == Ty || isa<Constant>(V)) return false;
|
|
|
|
|
|
|
|
// If this is a noop cast, it isn't real codegen.
|
|
|
|
if (V->getType()->isLosslesslyConvertibleTo(Ty))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// If this is another cast that can be elimianted, it isn't codegen either.
|
|
|
|
if (const CastInst *CI = dyn_cast<CastInst>(V))
|
|
|
|
if (isEliminableCastOfCast(CI->getOperand(0)->getType(), CI->getType(), Ty,
|
|
|
|
TD))
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// InsertOperandCastBefore - This inserts a cast of V to DestTy before the
|
|
|
|
/// InsertBefore instruction. This is specialized a bit to avoid inserting
|
|
|
|
/// casts that are known to not do anything...
|
|
|
|
///
|
|
|
|
Value *InstCombiner::InsertOperandCastBefore(Value *V, const Type *DestTy,
|
|
|
|
Instruction *InsertBefore) {
|
|
|
|
if (V->getType() == DestTy) return V;
|
|
|
|
if (Constant *C = dyn_cast<Constant>(V))
|
|
|
|
return ConstantExpr::getCast(C, DestTy);
|
|
|
|
|
|
|
|
CastInst *CI = new CastInst(V, DestTy, V->getName());
|
|
|
|
InsertNewInstBefore(CI, *InsertBefore);
|
|
|
|
return CI;
|
|
|
|
}
|
|
|
|
|
2003-03-10 21:43:22 +00:00
|
|
|
// SimplifyCommutative - This performs a few simplifications for commutative
|
|
|
|
// operators:
|
|
|
|
//
|
|
|
|
// 1. Order operands such that they are listed from right (least complex) to
|
|
|
|
// left (most complex). This puts constants before unary operators before
|
|
|
|
// binary operators.
|
2002-04-18 17:39:14 +00:00
|
|
|
//
|
2003-03-11 00:12:48 +00:00
|
|
|
// 2. Transform: (op (op V, C1), C2) ==> (op V, (op C1, C2))
|
|
|
|
// 3. Transform: (op (op V1, C1), (op V2, C2)) ==> (op (op V1, V2), (op C1,C2))
|
2003-03-10 21:43:22 +00:00
|
|
|
//
|
2003-03-11 00:12:48 +00:00
|
|
|
bool InstCombiner::SimplifyCommutative(BinaryOperator &I) {
|
2003-03-10 21:43:22 +00:00
|
|
|
bool Changed = false;
|
|
|
|
if (getComplexity(I.getOperand(0)) < getComplexity(I.getOperand(1)))
|
|
|
|
Changed = !I.swapOperands();
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2003-03-10 21:43:22 +00:00
|
|
|
if (!I.isAssociative()) return Changed;
|
|
|
|
Instruction::BinaryOps Opcode = I.getOpcode();
|
2003-03-11 00:12:48 +00:00
|
|
|
if (BinaryOperator *Op = dyn_cast<BinaryOperator>(I.getOperand(0)))
|
|
|
|
if (Op->getOpcode() == Opcode && isa<Constant>(Op->getOperand(1))) {
|
|
|
|
if (isa<Constant>(I.getOperand(1))) {
|
2003-05-27 16:40:51 +00:00
|
|
|
Constant *Folded = ConstantExpr::get(I.getOpcode(),
|
|
|
|
cast<Constant>(I.getOperand(1)),
|
|
|
|
cast<Constant>(Op->getOperand(1)));
|
2003-03-11 00:12:48 +00:00
|
|
|
I.setOperand(0, Op->getOperand(0));
|
|
|
|
I.setOperand(1, Folded);
|
|
|
|
return true;
|
|
|
|
} else if (BinaryOperator *Op1=dyn_cast<BinaryOperator>(I.getOperand(1)))
|
|
|
|
if (Op1->getOpcode() == Opcode && isa<Constant>(Op1->getOperand(1)) &&
|
|
|
|
isOnlyUse(Op) && isOnlyUse(Op1)) {
|
|
|
|
Constant *C1 = cast<Constant>(Op->getOperand(1));
|
|
|
|
Constant *C2 = cast<Constant>(Op1->getOperand(1));
|
|
|
|
|
|
|
|
// Fold (op (op V1, C1), (op V2, C2)) ==> (op (op V1, V2), (op C1,C2))
|
2003-05-27 16:40:51 +00:00
|
|
|
Constant *Folded = ConstantExpr::get(I.getOpcode(), C1, C2);
|
2003-03-11 00:12:48 +00:00
|
|
|
Instruction *New = BinaryOperator::create(Opcode, Op->getOperand(0),
|
|
|
|
Op1->getOperand(0),
|
|
|
|
Op1->getName(), &I);
|
|
|
|
WorkList.push_back(New);
|
|
|
|
I.setOperand(0, New);
|
|
|
|
I.setOperand(1, Folded);
|
|
|
|
return true;
|
2005-04-21 23:48:37 +00:00
|
|
|
}
|
2003-03-10 21:43:22 +00:00
|
|
|
}
|
|
|
|
return Changed;
|
2002-04-18 17:39:14 +00:00
|
|
|
}
|
2001-12-14 16:52:21 +00:00
|
|
|
|
2003-03-10 23:06:50 +00:00
|
|
|
// dyn_castNegVal - Given a 'sub' instruction, return the RHS of the instruction
|
|
|
|
// if the LHS is a constant zero (which is the 'negate' form).
|
2002-05-06 16:49:18 +00:00
|
|
|
//
|
2003-03-10 23:06:50 +00:00
|
|
|
static inline Value *dyn_castNegVal(Value *V) {
|
|
|
|
if (BinaryOperator::isNeg(V))
|
2005-04-24 07:30:14 +00:00
|
|
|
return BinaryOperator::getNegArgument(V);
|
2003-03-10 23:06:50 +00:00
|
|
|
|
2004-12-14 20:08:06 +00:00
|
|
|
// Constants can be considered to be negated values if they can be folded.
|
|
|
|
if (ConstantInt *C = dyn_cast<ConstantInt>(V))
|
|
|
|
return ConstantExpr::getNeg(C);
|
2003-03-10 23:06:50 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline Value *dyn_castNotVal(Value *V) {
|
|
|
|
if (BinaryOperator::isNot(V))
|
2005-04-24 07:30:14 +00:00
|
|
|
return BinaryOperator::getNotArgument(V);
|
2003-03-10 23:06:50 +00:00
|
|
|
|
|
|
|
// Constants can be considered to be not'ed values...
|
2003-04-30 22:34:06 +00:00
|
|
|
if (ConstantIntegral *C = dyn_cast<ConstantIntegral>(V))
|
2004-06-10 02:12:35 +00:00
|
|
|
return ConstantExpr::getNot(C);
|
2003-03-10 23:06:50 +00:00
|
|
|
return 0;
|
2002-05-06 16:49:18 +00:00
|
|
|
}
|
|
|
|
|
2003-03-11 00:12:48 +00:00
|
|
|
// dyn_castFoldableMul - If this value is a multiply that can be folded into
|
|
|
|
// other computations (because it has a constant operand), return the
|
2004-11-13 19:50:12 +00:00
|
|
|
// non-constant operand of the multiply, and set CST to point to the multiplier.
|
|
|
|
// Otherwise, return null.
|
2003-03-11 00:12:48 +00:00
|
|
|
//
|
2004-11-13 19:50:12 +00:00
|
|
|
static inline Value *dyn_castFoldableMul(Value *V, ConstantInt *&CST) {
|
2003-10-15 16:48:29 +00:00
|
|
|
if (V->hasOneUse() && V->getType()->isInteger())
|
2004-11-13 19:50:12 +00:00
|
|
|
if (Instruction *I = dyn_cast<Instruction>(V)) {
|
2003-03-11 00:12:48 +00:00
|
|
|
if (I->getOpcode() == Instruction::Mul)
|
2004-11-15 05:54:07 +00:00
|
|
|
if ((CST = dyn_cast<ConstantInt>(I->getOperand(1))))
|
2003-03-11 00:12:48 +00:00
|
|
|
return I->getOperand(0);
|
2004-11-13 19:50:12 +00:00
|
|
|
if (I->getOpcode() == Instruction::Shl)
|
2004-11-15 05:54:07 +00:00
|
|
|
if ((CST = dyn_cast<ConstantInt>(I->getOperand(1)))) {
|
2004-11-13 19:50:12 +00:00
|
|
|
// The multiplier is really 1 << CST.
|
|
|
|
Constant *One = ConstantInt::get(V->getType(), 1);
|
|
|
|
CST = cast<ConstantInt>(ConstantExpr::getShl(One, CST));
|
|
|
|
return I->getOperand(0);
|
|
|
|
}
|
|
|
|
}
|
2003-03-11 00:12:48 +00:00
|
|
|
return 0;
|
2003-02-18 19:28:33 +00:00
|
|
|
}
|
2002-08-14 17:51:49 +00:00
|
|
|
|
2005-01-13 20:14:25 +00:00
|
|
|
/// dyn_castGetElementPtr - If this is a getelementptr instruction or constant
|
|
|
|
/// expression, return it.
|
|
|
|
static User *dyn_castGetElementPtr(Value *V) {
|
|
|
|
if (isa<GetElementPtrInst>(V)) return cast<User>(V);
|
|
|
|
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V))
|
|
|
|
if (CE->getOpcode() == Instruction::GetElementPtr)
|
|
|
|
return cast<User>(V);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
Fold (and (setcc X, C1), (setcc X, C2))
This is important for several reasons:
1. Benchmarks have lots of code that looks like this (perlbmk in particular):
%tmp.2.i = setne int %tmp.0.i, 128 ; <bool> [#uses=1]
%tmp.6343 = seteq int %tmp.0.i, 1 ; <bool> [#uses=1]
%tmp.63 = and bool %tmp.2.i, %tmp.6343 ; <bool> [#uses=1]
we now fold away the setne, a clear improvement.
2. In the more important cases, such as (X >= 10) & (X < 20), we now produce
smaller code: (X-10) < 10.
3. Perhaps the nicest effect of this patch is that it really helps out the
code generators. In particular, for a 'range test' like the above,
instead of generating this on X86 (the difference on PPC is even more
pronounced):
cmp %EAX, 50
setge %CL
cmp %EAX, 100
setl %AL
and %CL, %AL
cmp %CL, 0
we now generate this:
add %EAX, -50
cmp %EAX, 50
Furthermore, this causes setcc's to be folded into branches more often.
These combinations trigger dozens of times in the spec benchmarks, particularly
in 176.gcc, 186.crafty, 253.perlbmk, 254.gap, & 099.go.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16559 91177308-0d34-0410-b5e6-96231b3b80d8
2004-09-28 21:48:02 +00:00
|
|
|
// AddOne, SubOne - Add or subtract a constant one from an integer constant...
|
2004-09-29 17:40:11 +00:00
|
|
|
static ConstantInt *AddOne(ConstantInt *C) {
|
|
|
|
return cast<ConstantInt>(ConstantExpr::getAdd(C,
|
|
|
|
ConstantInt::get(C->getType(), 1)));
|
Fold (and (setcc X, C1), (setcc X, C2))
This is important for several reasons:
1. Benchmarks have lots of code that looks like this (perlbmk in particular):
%tmp.2.i = setne int %tmp.0.i, 128 ; <bool> [#uses=1]
%tmp.6343 = seteq int %tmp.0.i, 1 ; <bool> [#uses=1]
%tmp.63 = and bool %tmp.2.i, %tmp.6343 ; <bool> [#uses=1]
we now fold away the setne, a clear improvement.
2. In the more important cases, such as (X >= 10) & (X < 20), we now produce
smaller code: (X-10) < 10.
3. Perhaps the nicest effect of this patch is that it really helps out the
code generators. In particular, for a 'range test' like the above,
instead of generating this on X86 (the difference on PPC is even more
pronounced):
cmp %EAX, 50
setge %CL
cmp %EAX, 100
setl %AL
and %CL, %AL
cmp %CL, 0
we now generate this:
add %EAX, -50
cmp %EAX, 50
Furthermore, this causes setcc's to be folded into branches more often.
These combinations trigger dozens of times in the spec benchmarks, particularly
in 176.gcc, 186.crafty, 253.perlbmk, 254.gap, & 099.go.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16559 91177308-0d34-0410-b5e6-96231b3b80d8
2004-09-28 21:48:02 +00:00
|
|
|
}
|
2004-09-29 17:40:11 +00:00
|
|
|
static ConstantInt *SubOne(ConstantInt *C) {
|
|
|
|
return cast<ConstantInt>(ConstantExpr::getSub(C,
|
|
|
|
ConstantInt::get(C->getType(), 1)));
|
Fold (and (setcc X, C1), (setcc X, C2))
This is important for several reasons:
1. Benchmarks have lots of code that looks like this (perlbmk in particular):
%tmp.2.i = setne int %tmp.0.i, 128 ; <bool> [#uses=1]
%tmp.6343 = seteq int %tmp.0.i, 1 ; <bool> [#uses=1]
%tmp.63 = and bool %tmp.2.i, %tmp.6343 ; <bool> [#uses=1]
we now fold away the setne, a clear improvement.
2. In the more important cases, such as (X >= 10) & (X < 20), we now produce
smaller code: (X-10) < 10.
3. Perhaps the nicest effect of this patch is that it really helps out the
code generators. In particular, for a 'range test' like the above,
instead of generating this on X86 (the difference on PPC is even more
pronounced):
cmp %EAX, 50
setge %CL
cmp %EAX, 100
setl %AL
and %CL, %AL
cmp %CL, 0
we now generate this:
add %EAX, -50
cmp %EAX, 50
Furthermore, this causes setcc's to be folded into branches more often.
These combinations trigger dozens of times in the spec benchmarks, particularly
in 176.gcc, 186.crafty, 253.perlbmk, 254.gap, & 099.go.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16559 91177308-0d34-0410-b5e6-96231b3b80d8
2004-09-28 21:48:02 +00:00
|
|
|
}
|
|
|
|
|
2006-02-11 09:31:47 +00:00
|
|
|
/// GetConstantInType - Return a ConstantInt with the specified type and value.
|
|
|
|
///
|
2006-02-12 02:07:56 +00:00
|
|
|
static ConstantIntegral *GetConstantInType(const Type *Ty, uint64_t Val) {
|
2006-02-11 09:31:47 +00:00
|
|
|
if (Ty->isUnsigned())
|
|
|
|
return ConstantUInt::get(Ty, Val);
|
2006-02-12 02:07:56 +00:00
|
|
|
else if (Ty->getTypeID() == Type::BoolTyID)
|
|
|
|
return ConstantBool::get(Val);
|
2006-02-11 09:31:47 +00:00
|
|
|
int64_t SVal = Val;
|
|
|
|
SVal <<= 64-Ty->getPrimitiveSizeInBits();
|
|
|
|
SVal >>= 64-Ty->getPrimitiveSizeInBits();
|
|
|
|
return ConstantSInt::get(Ty, SVal);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-02-09 07:38:58 +00:00
|
|
|
/// ComputeMaskedBits - Determine which of the bits specified in Mask are
|
|
|
|
/// known to be either zero or one and return them in the KnownZero/KnownOne
|
|
|
|
/// bitsets. This code only analyzes bits in Mask, in order to short-circuit
|
|
|
|
/// processing.
|
|
|
|
static void ComputeMaskedBits(Value *V, uint64_t Mask, uint64_t &KnownZero,
|
|
|
|
uint64_t &KnownOne, unsigned Depth = 0) {
|
2005-09-24 23:43:33 +00:00
|
|
|
// Note, we cannot consider 'undef' to be "IsZero" here. The problem is that
|
|
|
|
// we cannot optimize based on the assumption that it is zero without changing
|
2006-02-07 07:27:52 +00:00
|
|
|
// it to be an explicit zero. If we don't change it to zero, other code could
|
2005-09-24 23:43:33 +00:00
|
|
|
// optimized based on the contradictory assumption that it is non-zero.
|
|
|
|
// Because instcombine aggressively folds operations with undef args anyway,
|
|
|
|
// this won't lose us code quality.
|
2006-02-09 07:38:58 +00:00
|
|
|
if (ConstantIntegral *CI = dyn_cast<ConstantIntegral>(V)) {
|
|
|
|
// We know all of the bits for a constant!
|
2006-02-11 09:31:47 +00:00
|
|
|
KnownOne = CI->getZExtValue() & Mask;
|
2006-02-09 07:38:58 +00:00
|
|
|
KnownZero = ~KnownOne & Mask;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
KnownZero = KnownOne = 0; // Don't know anything.
|
2006-02-07 08:05:22 +00:00
|
|
|
if (Depth == 6 || Mask == 0)
|
2006-02-09 07:38:58 +00:00
|
|
|
return; // Limit search depth.
|
|
|
|
|
|
|
|
uint64_t KnownZero2, KnownOne2;
|
2006-02-11 09:31:47 +00:00
|
|
|
Instruction *I = dyn_cast<Instruction>(V);
|
|
|
|
if (!I) return;
|
|
|
|
|
2006-05-04 17:33:35 +00:00
|
|
|
Mask &= V->getType()->getIntegralTypeMask();
|
|
|
|
|
2006-02-11 09:31:47 +00:00
|
|
|
switch (I->getOpcode()) {
|
|
|
|
case Instruction::And:
|
|
|
|
// If either the LHS or the RHS are Zero, the result is zero.
|
|
|
|
ComputeMaskedBits(I->getOperand(1), Mask, KnownZero, KnownOne, Depth+1);
|
|
|
|
Mask &= ~KnownZero;
|
|
|
|
ComputeMaskedBits(I->getOperand(0), Mask, KnownZero2, KnownOne2, Depth+1);
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
|
|
|
assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?");
|
|
|
|
|
|
|
|
// Output known-1 bits are only known if set in both the LHS & RHS.
|
|
|
|
KnownOne &= KnownOne2;
|
|
|
|
// Output known-0 are known to be clear if zero in either the LHS | RHS.
|
|
|
|
KnownZero |= KnownZero2;
|
|
|
|
return;
|
|
|
|
case Instruction::Or:
|
|
|
|
ComputeMaskedBits(I->getOperand(1), Mask, KnownZero, KnownOne, Depth+1);
|
|
|
|
Mask &= ~KnownOne;
|
|
|
|
ComputeMaskedBits(I->getOperand(0), Mask, KnownZero2, KnownOne2, Depth+1);
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
|
|
|
assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?");
|
|
|
|
|
|
|
|
// Output known-0 bits are only known if clear in both the LHS & RHS.
|
|
|
|
KnownZero &= KnownZero2;
|
|
|
|
// Output known-1 are known to be set if set in either the LHS | RHS.
|
|
|
|
KnownOne |= KnownOne2;
|
|
|
|
return;
|
|
|
|
case Instruction::Xor: {
|
|
|
|
ComputeMaskedBits(I->getOperand(1), Mask, KnownZero, KnownOne, Depth+1);
|
|
|
|
ComputeMaskedBits(I->getOperand(0), Mask, KnownZero2, KnownOne2, Depth+1);
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
|
|
|
assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?");
|
|
|
|
|
|
|
|
// Output known-0 bits are known if clear or set in both the LHS & RHS.
|
|
|
|
uint64_t KnownZeroOut = (KnownZero & KnownZero2) | (KnownOne & KnownOne2);
|
|
|
|
// Output known-1 are known to be set if set in only one of the LHS, RHS.
|
|
|
|
KnownOne = (KnownZero & KnownOne2) | (KnownOne & KnownZero2);
|
|
|
|
KnownZero = KnownZeroOut;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
case Instruction::Select:
|
|
|
|
ComputeMaskedBits(I->getOperand(2), Mask, KnownZero, KnownOne, Depth+1);
|
|
|
|
ComputeMaskedBits(I->getOperand(1), Mask, KnownZero2, KnownOne2, Depth+1);
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
|
|
|
assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?");
|
|
|
|
|
|
|
|
// Only known if known in both the LHS and RHS.
|
|
|
|
KnownOne &= KnownOne2;
|
|
|
|
KnownZero &= KnownZero2;
|
|
|
|
return;
|
|
|
|
case Instruction::Cast: {
|
|
|
|
const Type *SrcTy = I->getOperand(0)->getType();
|
|
|
|
if (!SrcTy->isIntegral()) return;
|
|
|
|
|
|
|
|
// If this is an integer truncate or noop, just look in the input.
|
|
|
|
if (SrcTy->getPrimitiveSizeInBits() >=
|
|
|
|
I->getType()->getPrimitiveSizeInBits()) {
|
|
|
|
ComputeMaskedBits(I->getOperand(0), Mask, KnownZero, KnownOne, Depth+1);
|
2006-02-09 07:38:58 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2006-02-11 09:31:47 +00:00
|
|
|
// Sign or Zero extension. Compute the bits in the result that are not
|
|
|
|
// present in the input.
|
|
|
|
uint64_t NotIn = ~SrcTy->getIntegralTypeMask();
|
|
|
|
uint64_t NewBits = I->getType()->getIntegralTypeMask() & NotIn;
|
2005-10-09 06:36:35 +00:00
|
|
|
|
2006-02-11 09:31:47 +00:00
|
|
|
// Handle zero extension.
|
|
|
|
if (!SrcTy->isSigned()) {
|
|
|
|
Mask &= SrcTy->getIntegralTypeMask();
|
|
|
|
ComputeMaskedBits(I->getOperand(0), Mask, KnownZero, KnownOne, Depth+1);
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
|
|
|
// The top bits are known to be zero.
|
|
|
|
KnownZero |= NewBits;
|
|
|
|
} else {
|
|
|
|
// Sign extension.
|
|
|
|
Mask &= SrcTy->getIntegralTypeMask();
|
|
|
|
ComputeMaskedBits(I->getOperand(0), Mask, KnownZero, KnownOne, Depth+1);
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
2006-02-07 08:05:22 +00:00
|
|
|
|
2006-02-11 09:31:47 +00:00
|
|
|
// If the sign bit of the input is known set or clear, then we know the
|
|
|
|
// top bits of the result.
|
|
|
|
uint64_t InSignBit = 1ULL << (SrcTy->getPrimitiveSizeInBits()-1);
|
|
|
|
if (KnownZero & InSignBit) { // Input sign bit known zero
|
2006-02-09 07:38:58 +00:00
|
|
|
KnownZero |= NewBits;
|
2006-02-11 09:31:47 +00:00
|
|
|
KnownOne &= ~NewBits;
|
|
|
|
} else if (KnownOne & InSignBit) { // Input sign bit known set
|
|
|
|
KnownOne |= NewBits;
|
|
|
|
KnownZero &= ~NewBits;
|
|
|
|
} else { // Input sign bit unknown
|
|
|
|
KnownZero &= ~NewBits;
|
|
|
|
KnownOne &= ~NewBits;
|
2006-02-09 07:38:58 +00:00
|
|
|
}
|
2006-02-11 09:31:47 +00:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
case Instruction::Shl:
|
|
|
|
// (shl X, C1) & C2 == 0 iff (X & C2 >>u C1) == 0
|
|
|
|
if (ConstantUInt *SA = dyn_cast<ConstantUInt>(I->getOperand(1))) {
|
|
|
|
Mask >>= SA->getValue();
|
|
|
|
ComputeMaskedBits(I->getOperand(0), Mask, KnownZero, KnownOne, Depth+1);
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
|
|
|
KnownZero <<= SA->getValue();
|
|
|
|
KnownOne <<= SA->getValue();
|
|
|
|
KnownZero |= (1ULL << SA->getValue())-1; // low bits known zero.
|
2006-02-09 07:38:58 +00:00
|
|
|
return;
|
2005-10-09 06:36:35 +00:00
|
|
|
}
|
2006-02-11 09:31:47 +00:00
|
|
|
break;
|
|
|
|
case Instruction::Shr:
|
|
|
|
// (ushr X, C1) & C2 == 0 iff (-1 >> C1) & C2 == 0
|
|
|
|
if (ConstantUInt *SA = dyn_cast<ConstantUInt>(I->getOperand(1))) {
|
|
|
|
// Compute the new bits that are at the top now.
|
|
|
|
uint64_t HighBits = (1ULL << SA->getValue())-1;
|
|
|
|
HighBits <<= I->getType()->getPrimitiveSizeInBits()-SA->getValue();
|
|
|
|
|
|
|
|
if (I->getType()->isUnsigned()) { // Unsigned shift right.
|
|
|
|
Mask <<= SA->getValue();
|
|
|
|
ComputeMaskedBits(I->getOperand(0), Mask, KnownZero,KnownOne,Depth+1);
|
|
|
|
assert((KnownZero & KnownOne) == 0&&"Bits known to be one AND zero?");
|
|
|
|
KnownZero >>= SA->getValue();
|
|
|
|
KnownOne >>= SA->getValue();
|
|
|
|
KnownZero |= HighBits; // high bits known zero.
|
|
|
|
} else {
|
|
|
|
Mask <<= SA->getValue();
|
|
|
|
ComputeMaskedBits(I->getOperand(0), Mask, KnownZero,KnownOne,Depth+1);
|
|
|
|
assert((KnownZero & KnownOne) == 0&&"Bits known to be one AND zero?");
|
|
|
|
KnownZero >>= SA->getValue();
|
|
|
|
KnownOne >>= SA->getValue();
|
2006-02-09 07:38:58 +00:00
|
|
|
|
2006-02-11 09:31:47 +00:00
|
|
|
// Handle the sign bits.
|
|
|
|
uint64_t SignBit = 1ULL << (I->getType()->getPrimitiveSizeInBits()-1);
|
|
|
|
SignBit >>= SA->getValue(); // Adjust to where it is now in the mask.
|
|
|
|
|
|
|
|
if (KnownZero & SignBit) { // New bits are known zero.
|
|
|
|
KnownZero |= HighBits;
|
|
|
|
} else if (KnownOne & SignBit) { // New bits are known one.
|
|
|
|
KnownOne |= HighBits;
|
2005-10-09 06:36:35 +00:00
|
|
|
}
|
2006-02-09 07:38:58 +00:00
|
|
|
}
|
2006-02-11 09:31:47 +00:00
|
|
|
return;
|
2005-09-24 23:43:33 +00:00
|
|
|
}
|
2006-02-11 09:31:47 +00:00
|
|
|
break;
|
2005-09-24 23:43:33 +00:00
|
|
|
}
|
2006-02-07 08:05:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// MaskedValueIsZero - Return true if 'V & Mask' is known to be zero. We use
|
|
|
|
/// this predicate to simplify operations downstream. Mask is known to be zero
|
|
|
|
/// for bits that V cannot have.
|
|
|
|
static bool MaskedValueIsZero(Value *V, uint64_t Mask, unsigned Depth = 0) {
|
2006-02-09 07:38:58 +00:00
|
|
|
uint64_t KnownZero, KnownOne;
|
|
|
|
ComputeMaskedBits(V, Mask, KnownZero, KnownOne, Depth);
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
|
|
|
return (KnownZero & Mask) == Mask;
|
2005-09-24 23:43:33 +00:00
|
|
|
}
|
|
|
|
|
2006-02-11 09:31:47 +00:00
|
|
|
/// ShrinkDemandedConstant - Check to see if the specified operand of the
|
|
|
|
/// specified instruction is a constant integer. If so, check to see if there
|
|
|
|
/// are any bits set in the constant that are not demanded. If so, shrink the
|
|
|
|
/// constant and return true.
|
|
|
|
static bool ShrinkDemandedConstant(Instruction *I, unsigned OpNo,
|
|
|
|
uint64_t Demanded) {
|
|
|
|
ConstantInt *OpC = dyn_cast<ConstantInt>(I->getOperand(OpNo));
|
|
|
|
if (!OpC) return false;
|
|
|
|
|
|
|
|
// If there are no bits set that aren't demanded, nothing to do.
|
|
|
|
if ((~Demanded & OpC->getZExtValue()) == 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// This is producing any bits that are not needed, shrink the RHS.
|
|
|
|
uint64_t Val = Demanded & OpC->getZExtValue();
|
|
|
|
I->setOperand(OpNo, GetConstantInType(OpC->getType(), Val));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2006-02-12 02:07:56 +00:00
|
|
|
// ComputeSignedMinMaxValuesFromKnownBits - Given a signed integer type and a
|
|
|
|
// set of known zero and one bits, compute the maximum and minimum values that
|
|
|
|
// could have the specified known zero and known one bits, returning them in
|
|
|
|
// min/max.
|
|
|
|
static void ComputeSignedMinMaxValuesFromKnownBits(const Type *Ty,
|
|
|
|
uint64_t KnownZero,
|
|
|
|
uint64_t KnownOne,
|
|
|
|
int64_t &Min, int64_t &Max) {
|
|
|
|
uint64_t TypeBits = Ty->getIntegralTypeMask();
|
|
|
|
uint64_t UnknownBits = ~(KnownZero|KnownOne) & TypeBits;
|
|
|
|
|
|
|
|
uint64_t SignBit = 1ULL << (Ty->getPrimitiveSizeInBits()-1);
|
|
|
|
|
|
|
|
// The minimum value is when all unknown bits are zeros, EXCEPT for the sign
|
|
|
|
// bit if it is unknown.
|
|
|
|
Min = KnownOne;
|
|
|
|
Max = KnownOne|UnknownBits;
|
|
|
|
|
|
|
|
if (SignBit & UnknownBits) { // Sign bit is unknown
|
|
|
|
Min |= SignBit;
|
|
|
|
Max &= ~SignBit;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sign extend the min/max values.
|
|
|
|
int ShAmt = 64-Ty->getPrimitiveSizeInBits();
|
|
|
|
Min = (Min << ShAmt) >> ShAmt;
|
|
|
|
Max = (Max << ShAmt) >> ShAmt;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ComputeUnsignedMinMaxValuesFromKnownBits - Given an unsigned integer type and
|
|
|
|
// a set of known zero and one bits, compute the maximum and minimum values that
|
|
|
|
// could have the specified known zero and known one bits, returning them in
|
|
|
|
// min/max.
|
|
|
|
static void ComputeUnsignedMinMaxValuesFromKnownBits(const Type *Ty,
|
|
|
|
uint64_t KnownZero,
|
|
|
|
uint64_t KnownOne,
|
|
|
|
uint64_t &Min,
|
|
|
|
uint64_t &Max) {
|
|
|
|
uint64_t TypeBits = Ty->getIntegralTypeMask();
|
|
|
|
uint64_t UnknownBits = ~(KnownZero|KnownOne) & TypeBits;
|
|
|
|
|
|
|
|
// The minimum value is when the unknown bits are all zeros.
|
|
|
|
Min = KnownOne;
|
|
|
|
// The maximum value is when the unknown bits are all ones.
|
|
|
|
Max = KnownOne|UnknownBits;
|
|
|
|
}
|
2006-02-11 09:31:47 +00:00
|
|
|
|
|
|
|
|
|
|
|
/// SimplifyDemandedBits - Look at V. At this point, we know that only the
|
|
|
|
/// DemandedMask bits of the result of V are ever used downstream. If we can
|
|
|
|
/// use this information to simplify V, do so and return true. Otherwise,
|
|
|
|
/// analyze the expression and return a mask of KnownOne and KnownZero bits for
|
|
|
|
/// the expression (used to simplify the caller). The KnownZero/One bits may
|
|
|
|
/// only be accurate for those bits in the DemandedMask.
|
|
|
|
bool InstCombiner::SimplifyDemandedBits(Value *V, uint64_t DemandedMask,
|
|
|
|
uint64_t &KnownZero, uint64_t &KnownOne,
|
2006-02-07 06:56:34 +00:00
|
|
|
unsigned Depth) {
|
2006-02-11 09:31:47 +00:00
|
|
|
if (ConstantIntegral *CI = dyn_cast<ConstantIntegral>(V)) {
|
|
|
|
// We know all of the bits for a constant!
|
|
|
|
KnownOne = CI->getZExtValue() & DemandedMask;
|
|
|
|
KnownZero = ~KnownOne & DemandedMask;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
KnownZero = KnownOne = 0;
|
2006-02-07 06:56:34 +00:00
|
|
|
if (!V->hasOneUse()) { // Other users may use these bits.
|
2006-02-11 09:31:47 +00:00
|
|
|
if (Depth != 0) { // Not at the root.
|
|
|
|
// Just compute the KnownZero/KnownOne bits to simplify things downstream.
|
|
|
|
ComputeMaskedBits(V, DemandedMask, KnownZero, KnownOne, Depth);
|
2006-02-07 06:56:34 +00:00
|
|
|
return false;
|
2006-02-11 09:31:47 +00:00
|
|
|
}
|
2006-02-07 06:56:34 +00:00
|
|
|
// If this is the root being simplified, allow it to have multiple uses,
|
2006-02-11 09:31:47 +00:00
|
|
|
// just set the DemandedMask to all bits.
|
|
|
|
DemandedMask = V->getType()->getIntegralTypeMask();
|
|
|
|
} else if (DemandedMask == 0) { // Not demanding any bits from V.
|
2006-02-07 08:05:22 +00:00
|
|
|
if (V != UndefValue::get(V->getType()))
|
|
|
|
return UpdateValueUsesWith(V, UndefValue::get(V->getType()));
|
|
|
|
return false;
|
2006-02-07 06:56:34 +00:00
|
|
|
} else if (Depth == 6) { // Limit search depth.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
Instruction *I = dyn_cast<Instruction>(V);
|
|
|
|
if (!I) return false; // Only analyze instructions.
|
|
|
|
|
2006-05-04 17:33:35 +00:00
|
|
|
DemandedMask &= V->getType()->getIntegralTypeMask();
|
|
|
|
|
2006-02-11 09:31:47 +00:00
|
|
|
uint64_t KnownZero2, KnownOne2;
|
2006-02-07 06:56:34 +00:00
|
|
|
switch (I->getOpcode()) {
|
|
|
|
default: break;
|
|
|
|
case Instruction::And:
|
2006-02-11 09:31:47 +00:00
|
|
|
// If either the LHS or the RHS are Zero, the result is zero.
|
|
|
|
if (SimplifyDemandedBits(I->getOperand(1), DemandedMask,
|
|
|
|
KnownZero, KnownOne, Depth+1))
|
|
|
|
return true;
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
|
|
|
|
|
|
|
// If something is known zero on the RHS, the bits aren't demanded on the
|
|
|
|
// LHS.
|
|
|
|
if (SimplifyDemandedBits(I->getOperand(0), DemandedMask & ~KnownZero,
|
|
|
|
KnownZero2, KnownOne2, Depth+1))
|
|
|
|
return true;
|
|
|
|
assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?");
|
|
|
|
|
|
|
|
// If all of the demanded bits are known one on one side, return the other.
|
|
|
|
// These bits cannot contribute to the result of the 'and'.
|
|
|
|
if ((DemandedMask & ~KnownZero2 & KnownOne) == (DemandedMask & ~KnownZero2))
|
|
|
|
return UpdateValueUsesWith(I, I->getOperand(0));
|
|
|
|
if ((DemandedMask & ~KnownZero & KnownOne2) == (DemandedMask & ~KnownZero))
|
|
|
|
return UpdateValueUsesWith(I, I->getOperand(1));
|
2006-02-12 08:02:11 +00:00
|
|
|
|
|
|
|
// If all of the demanded bits in the inputs are known zeros, return zero.
|
|
|
|
if ((DemandedMask & (KnownZero|KnownZero2)) == DemandedMask)
|
|
|
|
return UpdateValueUsesWith(I, Constant::getNullValue(I->getType()));
|
|
|
|
|
2006-02-11 09:31:47 +00:00
|
|
|
// If the RHS is a constant, see if we can simplify it.
|
2006-02-12 08:02:11 +00:00
|
|
|
if (ShrinkDemandedConstant(I, 1, DemandedMask & ~KnownZero2))
|
2006-02-11 09:31:47 +00:00
|
|
|
return UpdateValueUsesWith(I, I);
|
2006-02-07 06:56:34 +00:00
|
|
|
|
2006-02-11 09:31:47 +00:00
|
|
|
// Output known-1 bits are only known if set in both the LHS & RHS.
|
|
|
|
KnownOne &= KnownOne2;
|
|
|
|
// Output known-0 are known to be clear if zero in either the LHS | RHS.
|
|
|
|
KnownZero |= KnownZero2;
|
|
|
|
break;
|
|
|
|
case Instruction::Or:
|
|
|
|
if (SimplifyDemandedBits(I->getOperand(1), DemandedMask,
|
|
|
|
KnownZero, KnownOne, Depth+1))
|
|
|
|
return true;
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
|
|
|
if (SimplifyDemandedBits(I->getOperand(0), DemandedMask & ~KnownOne,
|
|
|
|
KnownZero2, KnownOne2, Depth+1))
|
|
|
|
return true;
|
|
|
|
assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?");
|
|
|
|
|
|
|
|
// If all of the demanded bits are known zero on one side, return the other.
|
|
|
|
// These bits cannot contribute to the result of the 'or'.
|
2006-02-18 03:20:33 +00:00
|
|
|
if ((DemandedMask & ~KnownOne2 & KnownZero) == (DemandedMask & ~KnownOne2))
|
2006-02-11 09:31:47 +00:00
|
|
|
return UpdateValueUsesWith(I, I->getOperand(0));
|
2006-02-18 03:20:33 +00:00
|
|
|
if ((DemandedMask & ~KnownOne & KnownZero2) == (DemandedMask & ~KnownOne))
|
2006-02-11 09:31:47 +00:00
|
|
|
return UpdateValueUsesWith(I, I->getOperand(1));
|
2006-02-12 08:02:11 +00:00
|
|
|
|
|
|
|
// If all of the potentially set bits on one side are known to be set on
|
|
|
|
// the other side, just use the 'other' side.
|
|
|
|
if ((DemandedMask & (~KnownZero) & KnownOne2) ==
|
|
|
|
(DemandedMask & (~KnownZero)))
|
|
|
|
return UpdateValueUsesWith(I, I->getOperand(0));
|
2006-02-16 21:11:51 +00:00
|
|
|
if ((DemandedMask & (~KnownZero2) & KnownOne) ==
|
|
|
|
(DemandedMask & (~KnownZero2)))
|
|
|
|
return UpdateValueUsesWith(I, I->getOperand(1));
|
2006-02-11 09:31:47 +00:00
|
|
|
|
|
|
|
// If the RHS is a constant, see if we can simplify it.
|
|
|
|
if (ShrinkDemandedConstant(I, 1, DemandedMask))
|
|
|
|
return UpdateValueUsesWith(I, I);
|
|
|
|
|
|
|
|
// Output known-0 bits are only known if clear in both the LHS & RHS.
|
|
|
|
KnownZero &= KnownZero2;
|
|
|
|
// Output known-1 are known to be set if set in either the LHS | RHS.
|
|
|
|
KnownOne |= KnownOne2;
|
|
|
|
break;
|
|
|
|
case Instruction::Xor: {
|
|
|
|
if (SimplifyDemandedBits(I->getOperand(1), DemandedMask,
|
|
|
|
KnownZero, KnownOne, Depth+1))
|
|
|
|
return true;
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
|
|
|
if (SimplifyDemandedBits(I->getOperand(0), DemandedMask,
|
|
|
|
KnownZero2, KnownOne2, Depth+1))
|
|
|
|
return true;
|
|
|
|
assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?");
|
|
|
|
|
|
|
|
// If all of the demanded bits are known zero on one side, return the other.
|
|
|
|
// These bits cannot contribute to the result of the 'xor'.
|
|
|
|
if ((DemandedMask & KnownZero) == DemandedMask)
|
|
|
|
return UpdateValueUsesWith(I, I->getOperand(0));
|
|
|
|
if ((DemandedMask & KnownZero2) == DemandedMask)
|
|
|
|
return UpdateValueUsesWith(I, I->getOperand(1));
|
|
|
|
|
|
|
|
// Output known-0 bits are known if clear or set in both the LHS & RHS.
|
|
|
|
uint64_t KnownZeroOut = (KnownZero & KnownZero2) | (KnownOne & KnownOne2);
|
|
|
|
// Output known-1 are known to be set if set in only one of the LHS, RHS.
|
|
|
|
uint64_t KnownOneOut = (KnownZero & KnownOne2) | (KnownOne & KnownZero2);
|
|
|
|
|
|
|
|
// If all of the unknown bits are known to be zero on one side or the other
|
|
|
|
// (but not both) turn this into an *inclusive* or.
|
2006-02-12 08:02:11 +00:00
|
|
|
// e.g. (A & C1)^(B & C2) -> (A & C1)|(B & C2) iff C1&C2 == 0
|
2006-02-11 09:31:47 +00:00
|
|
|
if (uint64_t UnknownBits = DemandedMask & ~(KnownZeroOut|KnownOneOut)) {
|
|
|
|
if ((UnknownBits & (KnownZero|KnownZero2)) == UnknownBits) {
|
|
|
|
Instruction *Or =
|
|
|
|
BinaryOperator::createOr(I->getOperand(0), I->getOperand(1),
|
|
|
|
I->getName());
|
|
|
|
InsertNewInstBefore(Or, *I);
|
|
|
|
return UpdateValueUsesWith(I, Or);
|
|
|
|
}
|
2006-02-07 06:56:34 +00:00
|
|
|
}
|
2006-02-11 09:31:47 +00:00
|
|
|
|
2006-02-12 08:02:11 +00:00
|
|
|
// If all of the demanded bits on one side are known, and all of the set
|
|
|
|
// bits on that side are also known to be set on the other side, turn this
|
|
|
|
// into an AND, as we know the bits will be cleared.
|
|
|
|
// e.g. (X | C1) ^ C2 --> (X | C1) & ~C2 iff (C1&C2) == C2
|
|
|
|
if ((DemandedMask & (KnownZero|KnownOne)) == DemandedMask) { // all known
|
|
|
|
if ((KnownOne & KnownOne2) == KnownOne) {
|
|
|
|
Constant *AndC = GetConstantInType(I->getType(),
|
|
|
|
~KnownOne & DemandedMask);
|
|
|
|
Instruction *And =
|
|
|
|
BinaryOperator::createAnd(I->getOperand(0), AndC, "tmp");
|
|
|
|
InsertNewInstBefore(And, *I);
|
|
|
|
return UpdateValueUsesWith(I, And);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-02-11 09:31:47 +00:00
|
|
|
// If the RHS is a constant, see if we can simplify it.
|
|
|
|
// FIXME: for XOR, we prefer to force bits to 1 if they will make a -1.
|
|
|
|
if (ShrinkDemandedConstant(I, 1, DemandedMask))
|
|
|
|
return UpdateValueUsesWith(I, I);
|
|
|
|
|
|
|
|
KnownZero = KnownZeroOut;
|
|
|
|
KnownOne = KnownOneOut;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Instruction::Select:
|
|
|
|
if (SimplifyDemandedBits(I->getOperand(2), DemandedMask,
|
|
|
|
KnownZero, KnownOne, Depth+1))
|
|
|
|
return true;
|
|
|
|
if (SimplifyDemandedBits(I->getOperand(1), DemandedMask,
|
|
|
|
KnownZero2, KnownOne2, Depth+1))
|
|
|
|
return true;
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
|
|
|
assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?");
|
|
|
|
|
|
|
|
// If the operands are constants, see if we can simplify them.
|
|
|
|
if (ShrinkDemandedConstant(I, 1, DemandedMask))
|
|
|
|
return UpdateValueUsesWith(I, I);
|
|
|
|
if (ShrinkDemandedConstant(I, 2, DemandedMask))
|
|
|
|
return UpdateValueUsesWith(I, I);
|
|
|
|
|
|
|
|
// Only known if known in both the LHS and RHS.
|
|
|
|
KnownOne &= KnownOne2;
|
|
|
|
KnownZero &= KnownZero2;
|
|
|
|
break;
|
2006-02-07 06:56:34 +00:00
|
|
|
case Instruction::Cast: {
|
|
|
|
const Type *SrcTy = I->getOperand(0)->getType();
|
2006-02-11 09:31:47 +00:00
|
|
|
if (!SrcTy->isIntegral()) return false;
|
2006-02-07 06:56:34 +00:00
|
|
|
|
2006-02-11 09:31:47 +00:00
|
|
|
// If this is an integer truncate or noop, just look in the input.
|
|
|
|
if (SrcTy->getPrimitiveSizeInBits() >=
|
|
|
|
I->getType()->getPrimitiveSizeInBits()) {
|
|
|
|
if (SimplifyDemandedBits(I->getOperand(0), DemandedMask,
|
|
|
|
KnownZero, KnownOne, Depth+1))
|
|
|
|
return true;
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sign or Zero extension. Compute the bits in the result that are not
|
|
|
|
// present in the input.
|
|
|
|
uint64_t NotIn = ~SrcTy->getIntegralTypeMask();
|
|
|
|
uint64_t NewBits = I->getType()->getIntegralTypeMask() & NotIn;
|
|
|
|
|
|
|
|
// Handle zero extension.
|
|
|
|
if (!SrcTy->isSigned()) {
|
|
|
|
DemandedMask &= SrcTy->getIntegralTypeMask();
|
|
|
|
if (SimplifyDemandedBits(I->getOperand(0), DemandedMask,
|
|
|
|
KnownZero, KnownOne, Depth+1))
|
|
|
|
return true;
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
|
|
|
// The top bits are known to be zero.
|
|
|
|
KnownZero |= NewBits;
|
|
|
|
} else {
|
|
|
|
// Sign extension.
|
2006-02-13 22:41:07 +00:00
|
|
|
uint64_t InSignBit = 1ULL << (SrcTy->getPrimitiveSizeInBits()-1);
|
|
|
|
int64_t InputDemandedBits = DemandedMask & SrcTy->getIntegralTypeMask();
|
|
|
|
|
|
|
|
// If any of the sign extended bits are demanded, we know that the sign
|
|
|
|
// bit is demanded.
|
|
|
|
if (NewBits & DemandedMask)
|
|
|
|
InputDemandedBits |= InSignBit;
|
|
|
|
|
|
|
|
if (SimplifyDemandedBits(I->getOperand(0), InputDemandedBits,
|
2006-02-11 09:31:47 +00:00
|
|
|
KnownZero, KnownOne, Depth+1))
|
|
|
|
return true;
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
|
|
|
|
|
|
|
// If the sign bit of the input is known set or clear, then we know the
|
|
|
|
// top bits of the result.
|
|
|
|
|
|
|
|
// If the input sign bit is known zero, or if the NewBits are not demanded
|
|
|
|
// convert this into a zero extension.
|
|
|
|
if ((KnownZero & InSignBit) || (NewBits & ~DemandedMask) == NewBits) {
|
2006-02-07 06:56:34 +00:00
|
|
|
// Convert to unsigned first.
|
2006-02-07 19:07:40 +00:00
|
|
|
Instruction *NewVal;
|
2006-02-07 06:56:34 +00:00
|
|
|
NewVal = new CastInst(I->getOperand(0), SrcTy->getUnsignedVersion(),
|
2006-02-07 19:07:40 +00:00
|
|
|
I->getOperand(0)->getName());
|
|
|
|
InsertNewInstBefore(NewVal, *I);
|
2006-02-11 09:31:47 +00:00
|
|
|
// Then cast that to the destination type.
|
2006-02-07 19:07:40 +00:00
|
|
|
NewVal = new CastInst(NewVal, I->getType(), I->getName());
|
|
|
|
InsertNewInstBefore(NewVal, *I);
|
2006-02-07 06:56:34 +00:00
|
|
|
return UpdateValueUsesWith(I, NewVal);
|
2006-02-11 09:31:47 +00:00
|
|
|
} else if (KnownOne & InSignBit) { // Input sign bit known set
|
|
|
|
KnownOne |= NewBits;
|
|
|
|
KnownZero &= ~NewBits;
|
|
|
|
} else { // Input sign bit unknown
|
|
|
|
KnownZero &= ~NewBits;
|
|
|
|
KnownOne &= ~NewBits;
|
2006-02-07 06:56:34 +00:00
|
|
|
}
|
|
|
|
}
|
2006-02-11 09:31:47 +00:00
|
|
|
break;
|
2006-02-07 06:56:34 +00:00
|
|
|
}
|
|
|
|
case Instruction::Shl:
|
2006-02-11 09:31:47 +00:00
|
|
|
if (ConstantUInt *SA = dyn_cast<ConstantUInt>(I->getOperand(1))) {
|
|
|
|
if (SimplifyDemandedBits(I->getOperand(0), DemandedMask >> SA->getValue(),
|
|
|
|
KnownZero, KnownOne, Depth+1))
|
|
|
|
return true;
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
|
|
|
KnownZero <<= SA->getValue();
|
|
|
|
KnownOne <<= SA->getValue();
|
|
|
|
KnownZero |= (1ULL << SA->getValue())-1; // low bits known zero.
|
|
|
|
}
|
2006-02-07 06:56:34 +00:00
|
|
|
break;
|
|
|
|
case Instruction::Shr:
|
2006-02-11 09:31:47 +00:00
|
|
|
if (ConstantUInt *SA = dyn_cast<ConstantUInt>(I->getOperand(1))) {
|
|
|
|
unsigned ShAmt = SA->getValue();
|
|
|
|
|
|
|
|
// Compute the new bits that are at the top now.
|
|
|
|
uint64_t HighBits = (1ULL << ShAmt)-1;
|
|
|
|
HighBits <<= I->getType()->getPrimitiveSizeInBits() - ShAmt;
|
2006-02-13 06:09:08 +00:00
|
|
|
uint64_t TypeMask = I->getType()->getIntegralTypeMask();
|
2006-02-11 09:31:47 +00:00
|
|
|
if (I->getType()->isUnsigned()) { // Unsigned shift right.
|
2006-02-13 06:09:08 +00:00
|
|
|
if (SimplifyDemandedBits(I->getOperand(0),
|
|
|
|
(DemandedMask << ShAmt) & TypeMask,
|
2006-02-11 09:31:47 +00:00
|
|
|
KnownZero, KnownOne, Depth+1))
|
|
|
|
return true;
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
2006-02-13 06:09:08 +00:00
|
|
|
KnownZero &= TypeMask;
|
|
|
|
KnownOne &= TypeMask;
|
2006-02-11 09:31:47 +00:00
|
|
|
KnownZero >>= ShAmt;
|
|
|
|
KnownOne >>= ShAmt;
|
|
|
|
KnownZero |= HighBits; // high bits known zero.
|
|
|
|
} else { // Signed shift right.
|
2006-02-13 06:09:08 +00:00
|
|
|
if (SimplifyDemandedBits(I->getOperand(0),
|
|
|
|
(DemandedMask << ShAmt) & TypeMask,
|
2006-02-11 09:31:47 +00:00
|
|
|
KnownZero, KnownOne, Depth+1))
|
|
|
|
return true;
|
|
|
|
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
|
2006-02-13 06:09:08 +00:00
|
|
|
KnownZero &= TypeMask;
|
|
|
|
KnownOne &= TypeMask;
|
2006-02-11 09:31:47 +00:00
|
|
|
KnownZero >>= SA->getValue();
|
|
|
|
KnownOne >>= SA->getValue();
|
|
|
|
|
|
|
|
// Handle the sign bits.
|
|
|
|
uint64_t SignBit = 1ULL << (I->getType()->getPrimitiveSizeInBits()-1);
|
|
|
|
SignBit >>= SA->getValue(); // Adjust to where it is now in the mask.
|
|
|
|
|
|
|
|
// If the input sign bit is known to be zero, or if none of the top bits
|
|
|
|
// are demanded, turn this into an unsigned shift right.
|
|
|
|
if ((KnownZero & SignBit) || (HighBits & ~DemandedMask) == HighBits) {
|
|
|
|
// Convert the input to unsigned.
|
|
|
|
Instruction *NewVal;
|
|
|
|
NewVal = new CastInst(I->getOperand(0),
|
|
|
|
I->getType()->getUnsignedVersion(),
|
|
|
|
I->getOperand(0)->getName());
|
|
|
|
InsertNewInstBefore(NewVal, *I);
|
|
|
|
// Perform the unsigned shift right.
|
|
|
|
NewVal = new ShiftInst(Instruction::Shr, NewVal, SA, I->getName());
|
|
|
|
InsertNewInstBefore(NewVal, *I);
|
|
|
|
// Then cast that to the destination type.
|
|
|
|
NewVal = new CastInst(NewVal, I->getType(), I->getName());
|
|
|
|
InsertNewInstBefore(NewVal, *I);
|
|
|
|
return UpdateValueUsesWith(I, NewVal);
|
|
|
|
} else if (KnownOne & SignBit) { // New bits are known one.
|
|
|
|
KnownOne |= HighBits;
|
|
|
|
}
|
2006-02-07 06:56:34 +00:00
|
|
|
}
|
2006-02-11 09:31:47 +00:00
|
|
|
}
|
2006-02-07 06:56:34 +00:00
|
|
|
break;
|
|
|
|
}
|
2006-02-11 09:31:47 +00:00
|
|
|
|
|
|
|
// If the client is only demanding bits that we know, return the known
|
|
|
|
// constant.
|
|
|
|
if ((DemandedMask & (KnownZero|KnownOne)) == DemandedMask)
|
|
|
|
return UpdateValueUsesWith(I, GetConstantInType(I->getType(), KnownOne));
|
2006-02-07 06:56:34 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
Fold (and (setcc X, C1), (setcc X, C2))
This is important for several reasons:
1. Benchmarks have lots of code that looks like this (perlbmk in particular):
%tmp.2.i = setne int %tmp.0.i, 128 ; <bool> [#uses=1]
%tmp.6343 = seteq int %tmp.0.i, 1 ; <bool> [#uses=1]
%tmp.63 = and bool %tmp.2.i, %tmp.6343 ; <bool> [#uses=1]
we now fold away the setne, a clear improvement.
2. In the more important cases, such as (X >= 10) & (X < 20), we now produce
smaller code: (X-10) < 10.
3. Perhaps the nicest effect of this patch is that it really helps out the
code generators. In particular, for a 'range test' like the above,
instead of generating this on X86 (the difference on PPC is even more
pronounced):
cmp %EAX, 50
setge %CL
cmp %EAX, 100
setl %AL
and %CL, %AL
cmp %CL, 0
we now generate this:
add %EAX, -50
cmp %EAX, 50
Furthermore, this causes setcc's to be folded into branches more often.
These combinations trigger dozens of times in the spec benchmarks, particularly
in 176.gcc, 186.crafty, 253.perlbmk, 254.gap, & 099.go.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16559 91177308-0d34-0410-b5e6-96231b3b80d8
2004-09-28 21:48:02 +00:00
|
|
|
// isTrueWhenEqual - Return true if the specified setcondinst instruction is
|
|
|
|
// true when both operands are equal...
|
|
|
|
//
|
|
|
|
static bool isTrueWhenEqual(Instruction &I) {
|
|
|
|
return I.getOpcode() == Instruction::SetEQ ||
|
|
|
|
I.getOpcode() == Instruction::SetGE ||
|
|
|
|
I.getOpcode() == Instruction::SetLE;
|
|
|
|
}
|
2003-08-13 19:01:45 +00:00
|
|
|
|
|
|
|
/// AssociativeOpt - Perform an optimization on an associative operator. This
|
|
|
|
/// function is designed to check a chain of associative operators for a
|
|
|
|
/// potential to apply a certain optimization. Since the optimization may be
|
|
|
|
/// applicable if the expression was reassociated, this checks the chain, then
|
|
|
|
/// reassociates the expression as necessary to expose the optimization
|
|
|
|
/// opportunity. This makes use of a special Functor, which must define
|
|
|
|
/// 'shouldApply' and 'apply' methods.
|
|
|
|
///
|
|
|
|
template<typename Functor>
|
|
|
|
Instruction *AssociativeOpt(BinaryOperator &Root, const Functor &F) {
|
|
|
|
unsigned Opcode = Root.getOpcode();
|
|
|
|
Value *LHS = Root.getOperand(0);
|
|
|
|
|
|
|
|
// Quick check, see if the immediate LHS matches...
|
|
|
|
if (F.shouldApply(LHS))
|
|
|
|
return F.apply(Root);
|
|
|
|
|
|
|
|
// Otherwise, if the LHS is not of the same opcode as the root, return.
|
|
|
|
Instruction *LHSI = dyn_cast<Instruction>(LHS);
|
2003-10-15 16:48:29 +00:00
|
|
|
while (LHSI && LHSI->getOpcode() == Opcode && LHSI->hasOneUse()) {
|
2003-08-13 19:01:45 +00:00
|
|
|
// Should we apply this transform to the RHS?
|
|
|
|
bool ShouldApply = F.shouldApply(LHSI->getOperand(1));
|
|
|
|
|
|
|
|
// If not to the RHS, check to see if we should apply to the LHS...
|
|
|
|
if (!ShouldApply && F.shouldApply(LHSI->getOperand(0))) {
|
|
|
|
cast<BinaryOperator>(LHSI)->swapOperands(); // Make the LHS the RHS
|
|
|
|
ShouldApply = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the functor wants to apply the optimization to the RHS of LHSI,
|
|
|
|
// reassociate the expression from ((? op A) op B) to (? op (A op B))
|
|
|
|
if (ShouldApply) {
|
|
|
|
BasicBlock *BB = Root.getParent();
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2003-08-13 19:01:45 +00:00
|
|
|
// Now all of the instructions are in the current basic block, go ahead
|
|
|
|
// and perform the reassociation.
|
|
|
|
Instruction *TmpLHSI = cast<Instruction>(Root.getOperand(0));
|
|
|
|
|
|
|
|
// First move the selected RHS to the LHS of the root...
|
|
|
|
Root.setOperand(0, LHSI->getOperand(1));
|
|
|
|
|
|
|
|
// Make what used to be the LHS of the root be the user of the root...
|
|
|
|
Value *ExtraOperand = TmpLHSI->getOperand(1);
|
2004-04-16 18:08:07 +00:00
|
|
|
if (&Root == TmpLHSI) {
|
2004-04-05 02:10:19 +00:00
|
|
|
Root.replaceAllUsesWith(Constant::getNullValue(TmpLHSI->getType()));
|
|
|
|
return 0;
|
|
|
|
}
|
2004-04-16 18:08:07 +00:00
|
|
|
Root.replaceAllUsesWith(TmpLHSI); // Users now use TmpLHSI
|
2003-08-13 19:01:45 +00:00
|
|
|
TmpLHSI->setOperand(1, &Root); // TmpLHSI now uses the root
|
2004-04-16 18:08:07 +00:00
|
|
|
TmpLHSI->getParent()->getInstList().remove(TmpLHSI);
|
|
|
|
BasicBlock::iterator ARI = &Root; ++ARI;
|
|
|
|
BB->getInstList().insert(ARI, TmpLHSI); // Move TmpLHSI to after Root
|
|
|
|
ARI = Root;
|
2003-08-13 19:01:45 +00:00
|
|
|
|
|
|
|
// Now propagate the ExtraOperand down the chain of instructions until we
|
|
|
|
// get to LHSI.
|
|
|
|
while (TmpLHSI != LHSI) {
|
|
|
|
Instruction *NextLHSI = cast<Instruction>(TmpLHSI->getOperand(0));
|
2004-04-16 18:08:07 +00:00
|
|
|
// Move the instruction to immediately before the chain we are
|
|
|
|
// constructing to avoid breaking dominance properties.
|
|
|
|
NextLHSI->getParent()->getInstList().remove(NextLHSI);
|
|
|
|
BB->getInstList().insert(ARI, NextLHSI);
|
|
|
|
ARI = NextLHSI;
|
|
|
|
|
2003-08-13 19:01:45 +00:00
|
|
|
Value *NextOp = NextLHSI->getOperand(1);
|
|
|
|
NextLHSI->setOperand(1, ExtraOperand);
|
|
|
|
TmpLHSI = NextLHSI;
|
|
|
|
ExtraOperand = NextOp;
|
|
|
|
}
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2003-08-13 19:01:45 +00:00
|
|
|
// Now that the instructions are reassociated, have the functor perform
|
|
|
|
// the transformation...
|
|
|
|
return F.apply(Root);
|
|
|
|
}
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2003-08-13 19:01:45 +00:00
|
|
|
LHSI = dyn_cast<Instruction>(LHSI->getOperand(0));
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// AddRHS - Implements: X + X --> X << 1
|
|
|
|
struct AddRHS {
|
|
|
|
Value *RHS;
|
|
|
|
AddRHS(Value *rhs) : RHS(rhs) {}
|
|
|
|
bool shouldApply(Value *LHS) const { return LHS == RHS; }
|
|
|
|
Instruction *apply(BinaryOperator &Add) const {
|
|
|
|
return new ShiftInst(Instruction::Shl, Add.getOperand(0),
|
|
|
|
ConstantInt::get(Type::UByteTy, 1));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// AddMaskingAnd - Implements (A & C1)+(B & C2) --> (A & C1)|(B & C2)
|
|
|
|
// iff C1&C2 == 0
|
|
|
|
struct AddMaskingAnd {
|
|
|
|
Constant *C2;
|
|
|
|
AddMaskingAnd(Constant *c) : C2(c) {}
|
|
|
|
bool shouldApply(Value *LHS) const {
|
2004-07-30 07:50:03 +00:00
|
|
|
ConstantInt *C1;
|
2005-04-21 23:48:37 +00:00
|
|
|
return match(LHS, m_And(m_Value(), m_ConstantInt(C1))) &&
|
2004-07-30 07:50:03 +00:00
|
|
|
ConstantExpr::getAnd(C1, C2)->isNullValue();
|
2003-08-13 19:01:45 +00:00
|
|
|
}
|
|
|
|
Instruction *apply(BinaryOperator &Add) const {
|
2004-06-10 02:07:29 +00:00
|
|
|
return BinaryOperator::createOr(Add.getOperand(0), Add.getOperand(1));
|
2003-08-13 19:01:45 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2005-01-01 16:22:27 +00:00
|
|
|
static Value *FoldOperationIntoSelectOperand(Instruction &I, Value *SO,
|
2004-04-09 19:05:30 +00:00
|
|
|
InstCombiner *IC) {
|
2005-01-01 16:22:27 +00:00
|
|
|
if (isa<CastInst>(I)) {
|
|
|
|
if (Constant *SOC = dyn_cast<Constant>(SO))
|
|
|
|
return ConstantExpr::getCast(SOC, I.getType());
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2005-01-01 16:22:27 +00:00
|
|
|
return IC->InsertNewInstBefore(new CastInst(SO, I.getType(),
|
|
|
|
SO->getName() + ".cast"), I);
|
|
|
|
}
|
|
|
|
|
2004-04-09 19:05:30 +00:00
|
|
|
// Figure out if the constant is the left or the right argument.
|
2005-01-01 16:22:27 +00:00
|
|
|
bool ConstIsRHS = isa<Constant>(I.getOperand(1));
|
|
|
|
Constant *ConstOperand = cast<Constant>(I.getOperand(ConstIsRHS));
|
2004-04-09 19:05:30 +00:00
|
|
|
|
|
|
|
if (Constant *SOC = dyn_cast<Constant>(SO)) {
|
|
|
|
if (ConstIsRHS)
|
2005-01-01 16:22:27 +00:00
|
|
|
return ConstantExpr::get(I.getOpcode(), SOC, ConstOperand);
|
|
|
|
return ConstantExpr::get(I.getOpcode(), ConstOperand, SOC);
|
2004-04-09 19:05:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Value *Op0 = SO, *Op1 = ConstOperand;
|
|
|
|
if (!ConstIsRHS)
|
|
|
|
std::swap(Op0, Op1);
|
|
|
|
Instruction *New;
|
2005-01-01 16:22:27 +00:00
|
|
|
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(&I))
|
|
|
|
New = BinaryOperator::create(BO->getOpcode(), Op0, Op1,SO->getName()+".op");
|
|
|
|
else if (ShiftInst *SI = dyn_cast<ShiftInst>(&I))
|
|
|
|
New = new ShiftInst(SI->getOpcode(), Op0, Op1, SO->getName()+".sh");
|
2004-04-10 19:15:56 +00:00
|
|
|
else {
|
2004-04-09 19:05:30 +00:00
|
|
|
assert(0 && "Unknown binary instruction type!");
|
2004-04-10 19:15:56 +00:00
|
|
|
abort();
|
|
|
|
}
|
2005-01-01 16:22:27 +00:00
|
|
|
return IC->InsertNewInstBefore(New, I);
|
|
|
|
}
|
|
|
|
|
|
|
|
// FoldOpIntoSelect - Given an instruction with a select as one operand and a
|
|
|
|
// constant as the other operand, try to fold the binary operator into the
|
|
|
|
// select arguments. This also works for Cast instructions, which obviously do
|
|
|
|
// not have a second operand.
|
|
|
|
static Instruction *FoldOpIntoSelect(Instruction &Op, SelectInst *SI,
|
|
|
|
InstCombiner *IC) {
|
|
|
|
// Don't modify shared select instructions
|
|
|
|
if (!SI->hasOneUse()) return 0;
|
|
|
|
Value *TV = SI->getOperand(1);
|
|
|
|
Value *FV = SI->getOperand(2);
|
|
|
|
|
|
|
|
if (isa<Constant>(TV) || isa<Constant>(FV)) {
|
2005-04-21 05:43:13 +00:00
|
|
|
// Bool selects with constant operands can be folded to logical ops.
|
|
|
|
if (SI->getType() == Type::BoolTy) return 0;
|
|
|
|
|
2005-01-01 16:22:27 +00:00
|
|
|
Value *SelectTrueVal = FoldOperationIntoSelectOperand(Op, TV, IC);
|
|
|
|
Value *SelectFalseVal = FoldOperationIntoSelectOperand(Op, FV, IC);
|
|
|
|
|
|
|
|
return new SelectInst(SI->getCondition(), SelectTrueVal,
|
|
|
|
SelectFalseVal);
|
|
|
|
}
|
|
|
|
return 0;
|
2004-04-09 19:05:30 +00:00
|
|
|
}
|
2003-08-13 19:01:45 +00:00
|
|
|
|
Fold binary expressions and casts into PHI nodes that have all constant inputs.
This takes something like this:
%A = phi int [ 3, %cond_false.0 ], [ 2, %endif.0.i ], [ 2, %endif.1.i ]
%B = div int %tmp.243, 4
and turns it into:
%A = phi int [ 3/4, %cond_false.0 ], [ 2/4, %endif.0.i ], [ 2/4, %endif.1.i ]
which is later simplified (in this case) into %A = 0.
This triggers thousands of times in spec, for example, 269 times in 176.gcc.
This is tested by InstCombine/add.ll:test23 and set.ll:test18.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16582 91177308-0d34-0410-b5e6-96231b3b80d8
2004-09-29 05:07:12 +00:00
|
|
|
|
|
|
|
/// FoldOpIntoPhi - Given a binary operator or cast instruction which has a PHI
|
|
|
|
/// node as operand #0, see if we can fold the instruction into the PHI (which
|
|
|
|
/// is only possible if all operands to the PHI are constants).
|
|
|
|
Instruction *InstCombiner::FoldOpIntoPhi(Instruction &I) {
|
|
|
|
PHINode *PN = cast<PHINode>(I.getOperand(0));
|
2004-11-14 19:13:23 +00:00
|
|
|
unsigned NumPHIValues = PN->getNumIncomingValues();
|
|
|
|
if (!PN->hasOneUse() || NumPHIValues == 0 ||
|
|
|
|
!isa<Constant>(PN->getIncomingValue(0))) return 0;
|
Fold binary expressions and casts into PHI nodes that have all constant inputs.
This takes something like this:
%A = phi int [ 3, %cond_false.0 ], [ 2, %endif.0.i ], [ 2, %endif.1.i ]
%B = div int %tmp.243, 4
and turns it into:
%A = phi int [ 3/4, %cond_false.0 ], [ 2/4, %endif.0.i ], [ 2/4, %endif.1.i ]
which is later simplified (in this case) into %A = 0.
This triggers thousands of times in spec, for example, 269 times in 176.gcc.
This is tested by InstCombine/add.ll:test23 and set.ll:test18.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16582 91177308-0d34-0410-b5e6-96231b3b80d8
2004-09-29 05:07:12 +00:00
|
|
|
|
|
|
|
// Check to see if all of the operands of the PHI are constants. If not, we
|
|
|
|
// cannot do the transformation.
|
2004-11-14 19:13:23 +00:00
|
|
|
for (unsigned i = 1; i != NumPHIValues; ++i)
|
Fold binary expressions and casts into PHI nodes that have all constant inputs.
This takes something like this:
%A = phi int [ 3, %cond_false.0 ], [ 2, %endif.0.i ], [ 2, %endif.1.i ]
%B = div int %tmp.243, 4
and turns it into:
%A = phi int [ 3/4, %cond_false.0 ], [ 2/4, %endif.0.i ], [ 2/4, %endif.1.i ]
which is later simplified (in this case) into %A = 0.
This triggers thousands of times in spec, for example, 269 times in 176.gcc.
This is tested by InstCombine/add.ll:test23 and set.ll:test18.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16582 91177308-0d34-0410-b5e6-96231b3b80d8
2004-09-29 05:07:12 +00:00
|
|
|
if (!isa<Constant>(PN->getIncomingValue(i)))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
// Okay, we can do the transformation: create the new PHI node.
|
|
|
|
PHINode *NewPN = new PHINode(I.getType(), I.getName());
|
|
|
|
I.setName("");
|
2005-01-29 00:39:08 +00:00
|
|
|
NewPN->reserveOperandSpace(PN->getNumOperands()/2);
|
Fold binary expressions and casts into PHI nodes that have all constant inputs.
This takes something like this:
%A = phi int [ 3, %cond_false.0 ], [ 2, %endif.0.i ], [ 2, %endif.1.i ]
%B = div int %tmp.243, 4
and turns it into:
%A = phi int [ 3/4, %cond_false.0 ], [ 2/4, %endif.0.i ], [ 2/4, %endif.1.i ]
which is later simplified (in this case) into %A = 0.
This triggers thousands of times in spec, for example, 269 times in 176.gcc.
This is tested by InstCombine/add.ll:test23 and set.ll:test18.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16582 91177308-0d34-0410-b5e6-96231b3b80d8
2004-09-29 05:07:12 +00:00
|
|
|
InsertNewInstBefore(NewPN, *PN);
|
|
|
|
|
|
|
|
// Next, add all of the operands to the PHI.
|
|
|
|
if (I.getNumOperands() == 2) {
|
|
|
|
Constant *C = cast<Constant>(I.getOperand(1));
|
2004-11-14 19:13:23 +00:00
|
|
|
for (unsigned i = 0; i != NumPHIValues; ++i) {
|
Fold binary expressions and casts into PHI nodes that have all constant inputs.
This takes something like this:
%A = phi int [ 3, %cond_false.0 ], [ 2, %endif.0.i ], [ 2, %endif.1.i ]
%B = div int %tmp.243, 4
and turns it into:
%A = phi int [ 3/4, %cond_false.0 ], [ 2/4, %endif.0.i ], [ 2/4, %endif.1.i ]
which is later simplified (in this case) into %A = 0.
This triggers thousands of times in spec, for example, 269 times in 176.gcc.
This is tested by InstCombine/add.ll:test23 and set.ll:test18.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16582 91177308-0d34-0410-b5e6-96231b3b80d8
2004-09-29 05:07:12 +00:00
|
|
|
Constant *InV = cast<Constant>(PN->getIncomingValue(i));
|
|
|
|
NewPN->addIncoming(ConstantExpr::get(I.getOpcode(), InV, C),
|
|
|
|
PN->getIncomingBlock(i));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
assert(isa<CastInst>(I) && "Unary op should be a cast!");
|
|
|
|
const Type *RetTy = I.getType();
|
2004-11-14 19:13:23 +00:00
|
|
|
for (unsigned i = 0; i != NumPHIValues; ++i) {
|
Fold binary expressions and casts into PHI nodes that have all constant inputs.
This takes something like this:
%A = phi int [ 3, %cond_false.0 ], [ 2, %endif.0.i ], [ 2, %endif.1.i ]
%B = div int %tmp.243, 4
and turns it into:
%A = phi int [ 3/4, %cond_false.0 ], [ 2/4, %endif.0.i ], [ 2/4, %endif.1.i ]
which is later simplified (in this case) into %A = 0.
This triggers thousands of times in spec, for example, 269 times in 176.gcc.
This is tested by InstCombine/add.ll:test23 and set.ll:test18.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16582 91177308-0d34-0410-b5e6-96231b3b80d8
2004-09-29 05:07:12 +00:00
|
|
|
Constant *InV = cast<Constant>(PN->getIncomingValue(i));
|
|
|
|
NewPN->addIncoming(ConstantExpr::getCast(InV, RetTy),
|
|
|
|
PN->getIncomingBlock(i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ReplaceInstUsesWith(I, NewPN);
|
|
|
|
}
|
|
|
|
|
2002-06-25 16:13:24 +00:00
|
|
|
Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
|
2003-03-10 21:43:22 +00:00
|
|
|
bool Changed = SimplifyCommutative(I);
|
2002-06-25 16:13:24 +00:00
|
|
|
Value *LHS = I.getOperand(0), *RHS = I.getOperand(1);
|
2002-05-06 16:49:18 +00:00
|
|
|
|
2004-04-10 22:01:55 +00:00
|
|
|
if (Constant *RHSC = dyn_cast<Constant>(RHS)) {
|
2004-10-16 18:11:37 +00:00
|
|
|
// X + undef -> undef
|
|
|
|
if (isa<UndefValue>(RHS))
|
|
|
|
return ReplaceInstUsesWith(I, RHS);
|
|
|
|
|
2004-04-10 22:01:55 +00:00
|
|
|
// X + 0 --> X
|
2005-10-17 17:56:38 +00:00
|
|
|
if (!I.getType()->isFloatingPoint()) { // NOTE: -0 + +0 = +0.
|
|
|
|
if (RHSC->isNullValue())
|
|
|
|
return ReplaceInstUsesWith(I, LHS);
|
2005-10-17 20:18:38 +00:00
|
|
|
} else if (ConstantFP *CFP = dyn_cast<ConstantFP>(RHSC)) {
|
|
|
|
if (CFP->isExactlyValue(-0.0))
|
|
|
|
return ReplaceInstUsesWith(I, LHS);
|
2005-10-17 17:56:38 +00:00
|
|
|
}
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2004-04-10 22:01:55 +00:00
|
|
|
// X + (signbit) --> X ^ signbit
|
|
|
|
if (ConstantInt *CI = dyn_cast<ConstantInt>(RHSC)) {
|
2006-02-07 08:05:22 +00:00
|
|
|
uint64_t Val = CI->getZExtValue();
|
2006-02-07 07:00:41 +00:00
|
|
|
if (Val == (1ULL << (CI->getType()->getPrimitiveSizeInBits()-1)))
|
2004-06-10 02:07:29 +00:00
|
|
|
return BinaryOperator::createXor(LHS, RHS);
|
2004-04-10 22:01:55 +00:00
|
|
|
}
|
Fold binary expressions and casts into PHI nodes that have all constant inputs.
This takes something like this:
%A = phi int [ 3, %cond_false.0 ], [ 2, %endif.0.i ], [ 2, %endif.1.i ]
%B = div int %tmp.243, 4
and turns it into:
%A = phi int [ 3/4, %cond_false.0 ], [ 2/4, %endif.0.i ], [ 2/4, %endif.1.i ]
which is later simplified (in this case) into %A = 0.
This triggers thousands of times in spec, for example, 269 times in 176.gcc.
This is tested by InstCombine/add.ll:test23 and set.ll:test18.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16582 91177308-0d34-0410-b5e6-96231b3b80d8
2004-09-29 05:07:12 +00:00
|
|
|
|
|
|
|
if (isa<PHINode>(LHS))
|
|
|
|
if (Instruction *NV = FoldOpIntoPhi(I))
|
|
|
|
return NV;
|
2005-09-24 23:43:33 +00:00
|
|
|
|
2006-01-06 17:59:59 +00:00
|
|
|
ConstantInt *XorRHS = 0;
|
|
|
|
Value *XorLHS = 0;
|
2005-09-24 23:43:33 +00:00
|
|
|
if (match(LHS, m_Xor(m_Value(XorLHS), m_ConstantInt(XorRHS)))) {
|
|
|
|
unsigned TySizeBits = I.getType()->getPrimitiveSizeInBits();
|
|
|
|
int64_t RHSSExt = cast<ConstantInt>(RHSC)->getSExtValue();
|
|
|
|
uint64_t RHSZExt = cast<ConstantInt>(RHSC)->getZExtValue();
|
|
|
|
|
|
|
|
uint64_t C0080Val = 1ULL << 31;
|
|
|
|
int64_t CFF80Val = -C0080Val;
|
|
|
|
unsigned Size = 32;
|
|
|
|
do {
|
|
|
|
if (TySizeBits > Size) {
|
|
|
|
bool Found = false;
|
|
|
|
// If we have ADD(XOR(AND(X, 0xFF), 0x80), 0xF..F80), it's a sext.
|
|
|
|
// If we have ADD(XOR(AND(X, 0xFF), 0xF..F80), 0x80), it's a sext.
|
|
|
|
if (RHSSExt == CFF80Val) {
|
|
|
|
if (XorRHS->getZExtValue() == C0080Val)
|
|
|
|
Found = true;
|
|
|
|
} else if (RHSZExt == C0080Val) {
|
|
|
|
if (XorRHS->getSExtValue() == CFF80Val)
|
|
|
|
Found = true;
|
|
|
|
}
|
|
|
|
if (Found) {
|
|
|
|
// This is a sign extend if the top bits are known zero.
|
2006-02-09 07:38:58 +00:00
|
|
|
uint64_t Mask = ~0ULL;
|
2006-02-07 07:27:52 +00:00
|
|
|
Mask <<= 64-(TySizeBits-Size);
|
2006-02-09 07:38:58 +00:00
|
|
|
Mask &= XorLHS->getType()->getIntegralTypeMask();
|
2006-02-07 07:27:52 +00:00
|
|
|
if (!MaskedValueIsZero(XorLHS, Mask))
|
2005-09-24 23:43:33 +00:00
|
|
|
Size = 0; // Not a sign ext, but can't be any others either.
|
|
|
|
goto FoundSExt;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Size >>= 1;
|
|
|
|
C0080Val >>= Size;
|
|
|
|
CFF80Val >>= Size;
|
|
|
|
} while (Size >= 8);
|
|
|
|
|
|
|
|
FoundSExt:
|
|
|
|
const Type *MiddleType = 0;
|
|
|
|
switch (Size) {
|
|
|
|
default: break;
|
|
|
|
case 32: MiddleType = Type::IntTy; break;
|
|
|
|
case 16: MiddleType = Type::ShortTy; break;
|
|
|
|
case 8: MiddleType = Type::SByteTy; break;
|
|
|
|
}
|
|
|
|
if (MiddleType) {
|
|
|
|
Instruction *NewTrunc = new CastInst(XorLHS, MiddleType, "sext");
|
|
|
|
InsertNewInstBefore(NewTrunc, I);
|
|
|
|
return new CastInst(NewTrunc, I.getType());
|
|
|
|
}
|
|
|
|
}
|
2004-04-10 22:01:55 +00:00
|
|
|
}
|
2002-05-06 16:49:18 +00:00
|
|
|
|
2003-08-13 19:01:45 +00:00
|
|
|
// X + X --> X << 1
|
2004-07-27 21:02:21 +00:00
|
|
|
if (I.getType()->isInteger()) {
|
2003-08-13 19:01:45 +00:00
|
|
|
if (Instruction *Result = AssociativeOpt(I, AddRHS(RHS))) return Result;
|
2005-04-07 17:14:51 +00:00
|
|
|
|
|
|
|
if (Instruction *RHSI = dyn_cast<Instruction>(RHS)) {
|
|
|
|
if (RHSI->getOpcode() == Instruction::Sub)
|
|
|
|
if (LHS == RHSI->getOperand(1)) // A + (B - A) --> B
|
|
|
|
return ReplaceInstUsesWith(I, RHSI->getOperand(0));
|
|
|
|
}
|
|
|
|
if (Instruction *LHSI = dyn_cast<Instruction>(LHS)) {
|
|
|
|
if (LHSI->getOpcode() == Instruction::Sub)
|
|
|
|
if (RHS == LHSI->getOperand(1)) // (B - A) + A --> B
|
|
|
|
return ReplaceInstUsesWith(I, LHSI->getOperand(0));
|
|
|
|
}
|
2004-07-27 21:02:21 +00:00
|
|
|
}
|
2003-08-13 04:18:28 +00:00
|
|
|
|
2002-05-08 22:46:53 +00:00
|
|
|
// -A + B --> B - A
|
2003-03-10 23:06:50 +00:00
|
|
|
if (Value *V = dyn_castNegVal(LHS))
|
2004-06-10 02:07:29 +00:00
|
|
|
return BinaryOperator::createSub(RHS, V);
|
2002-05-06 16:49:18 +00:00
|
|
|
|
|
|
|
// A + -B --> A - B
|
2003-03-10 23:06:50 +00:00
|
|
|
if (!isa<Constant>(RHS))
|
|
|
|
if (Value *V = dyn_castNegVal(RHS))
|
2004-06-10 02:07:29 +00:00
|
|
|
return BinaryOperator::createSub(LHS, V);
|
2002-04-18 17:39:14 +00:00
|
|
|
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2004-11-13 19:50:12 +00:00
|
|
|
ConstantInt *C2;
|
|
|
|
if (Value *X = dyn_castFoldableMul(LHS, C2)) {
|
|
|
|
if (X == RHS) // X*C + X --> X * (C+1)
|
|
|
|
return BinaryOperator::createMul(RHS, AddOne(C2));
|
|
|
|
|
|
|
|
// X*C1 + X*C2 --> X * (C1+C2)
|
|
|
|
ConstantInt *C1;
|
|
|
|
if (X == dyn_castFoldableMul(RHS, C1))
|
|
|
|
return BinaryOperator::createMul(X, ConstantExpr::getAdd(C1, C2));
|
2003-02-18 19:57:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// X + X*C --> X * (C+1)
|
2004-11-13 19:50:12 +00:00
|
|
|
if (dyn_castFoldableMul(RHS, C2) == LHS)
|
|
|
|
return BinaryOperator::createMul(LHS, AddOne(C2));
|
|
|
|
|
2003-02-18 19:57:07 +00:00
|
|
|
|
2003-08-13 19:01:45 +00:00
|
|
|
// (A & C1)+(B & C2) --> (A & C1)|(B & C2) iff C1&C2 == 0
|
2004-07-30 07:50:03 +00:00
|
|
|
if (match(RHS, m_And(m_Value(), m_ConstantInt(C2))))
|
2003-08-13 19:01:45 +00:00
|
|
|
if (Instruction *R = AssociativeOpt(I, AddMaskingAnd(C2))) return R;
|
2003-03-11 00:12:48 +00:00
|
|
|
|
2003-10-02 15:11:26 +00:00
|
|
|
if (ConstantInt *CRHS = dyn_cast<ConstantInt>(RHS)) {
|
2006-01-06 17:59:59 +00:00
|
|
|
Value *X = 0;
|
2004-07-30 07:50:03 +00:00
|
|
|
if (match(LHS, m_Not(m_Value(X)))) { // ~X + C --> (C-1) - X
|
|
|
|
Constant *C= ConstantExpr::getSub(CRHS, ConstantInt::get(I.getType(), 1));
|
|
|
|
return BinaryOperator::createSub(C, X);
|
2003-10-02 15:11:26 +00:00
|
|
|
}
|
2004-07-30 07:50:03 +00:00
|
|
|
|
2004-10-08 05:07:56 +00:00
|
|
|
// (X & FF00) + xx00 -> (X+xx00) & FF00
|
|
|
|
if (LHS->hasOneUse() && match(LHS, m_And(m_Value(X), m_ConstantInt(C2)))) {
|
|
|
|
Constant *Anded = ConstantExpr::getAnd(CRHS, C2);
|
|
|
|
if (Anded == CRHS) {
|
|
|
|
// See if all bits from the first bit set in the Add RHS up are included
|
|
|
|
// in the mask. First, get the rightmost bit.
|
|
|
|
uint64_t AddRHSV = CRHS->getRawValue();
|
|
|
|
|
|
|
|
// Form a mask of all bits from the lowest bit added through the top.
|
|
|
|
uint64_t AddRHSHighBits = ~((AddRHSV & -AddRHSV)-1);
|
2006-02-07 07:00:41 +00:00
|
|
|
AddRHSHighBits &= C2->getType()->getIntegralTypeMask();
|
2004-10-08 05:07:56 +00:00
|
|
|
|
|
|
|
// See if the and mask includes all of these bits.
|
|
|
|
uint64_t AddRHSHighBitsAnd = AddRHSHighBits & C2->getRawValue();
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2004-10-08 05:07:56 +00:00
|
|
|
if (AddRHSHighBits == AddRHSHighBitsAnd) {
|
|
|
|
// Okay, the xform is safe. Insert the new add pronto.
|
|
|
|
Value *NewAdd = InsertNewInstBefore(BinaryOperator::createAdd(X, CRHS,
|
|
|
|
LHS->getName()), I);
|
|
|
|
return BinaryOperator::createAnd(NewAdd, C2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-07-30 07:50:03 +00:00
|
|
|
// Try to fold constant add into select arguments.
|
|
|
|
if (SelectInst *SI = dyn_cast<SelectInst>(LHS))
|
2005-01-01 16:22:27 +00:00
|
|
|
if (Instruction *R = FoldOpIntoSelect(I, SI, this))
|
2004-07-30 07:50:03 +00:00
|
|
|
return R;
|
2003-10-02 15:11:26 +00:00
|
|
|
}
|
|
|
|
|
2002-06-25 16:13:24 +00:00
|
|
|
return Changed ? &I : 0;
|
2002-04-18 17:39:14 +00:00
|
|
|
}
|
2002-02-26 21:46:54 +00:00
|
|
|
|
2003-07-22 21:46:59 +00:00
|
|
|
// isSignBit - Return true if the value represented by the constant only has the
|
|
|
|
// highest order bit set.
|
|
|
|
static bool isSignBit(ConstantInt *CI) {
|
2005-04-24 06:59:08 +00:00
|
|
|
unsigned NumBits = CI->getType()->getPrimitiveSizeInBits();
|
2005-04-24 17:46:05 +00:00
|
|
|
return (CI->getRawValue() & (~0ULL >> (64-NumBits))) == (1ULL << (NumBits-1));
|
2003-07-22 21:46:59 +00:00
|
|
|
}
|
|
|
|
|
2004-03-13 00:11:49 +00:00
|
|
|
/// RemoveNoopCast - Strip off nonconverting casts from the value.
|
|
|
|
///
|
|
|
|
static Value *RemoveNoopCast(Value *V) {
|
|
|
|
if (CastInst *CI = dyn_cast<CastInst>(V)) {
|
|
|
|
const Type *CTy = CI->getType();
|
|
|
|
const Type *OpTy = CI->getOperand(0)->getType();
|
|
|
|
if (CTy->isInteger() && OpTy->isInteger()) {
|
2005-04-24 06:59:08 +00:00
|
|
|
if (CTy->getPrimitiveSizeInBits() == OpTy->getPrimitiveSizeInBits())
|
2004-03-13 00:11:49 +00:00
|
|
|
return RemoveNoopCast(CI->getOperand(0));
|
|
|
|
} else if (isa<PointerType>(CTy) && isa<PointerType>(OpTy))
|
|
|
|
return RemoveNoopCast(CI->getOperand(0));
|
|
|
|
}
|
|
|
|
return V;
|
|
|
|
}
|
|
|
|
|
2002-06-25 16:13:24 +00:00
|
|
|
Instruction *InstCombiner::visitSub(BinaryOperator &I) {
|
|
|
|
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
2002-05-06 16:14:14 +00:00
|
|
|
|
2002-08-12 21:17:25 +00:00
|
|
|
if (Op0 == Op1) // sub X, X -> 0
|
|
|
|
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
|
2002-04-18 17:39:14 +00:00
|
|
|
|
2002-08-12 21:17:25 +00:00
|
|
|
// If this is a 'B = x-(-A)', change to B = x+A...
|
2003-03-10 23:06:50 +00:00
|
|
|
if (Value *V = dyn_castNegVal(Op1))
|
2004-06-10 02:07:29 +00:00
|
|
|
return BinaryOperator::createAdd(Op0, V);
|
2002-05-06 16:49:18 +00:00
|
|
|
|
2004-10-16 18:11:37 +00:00
|
|
|
if (isa<UndefValue>(Op0))
|
|
|
|
return ReplaceInstUsesWith(I, Op0); // undef - X -> undef
|
|
|
|
if (isa<UndefValue>(Op1))
|
|
|
|
return ReplaceInstUsesWith(I, Op1); // X - undef -> undef
|
|
|
|
|
2003-11-05 01:06:05 +00:00
|
|
|
if (ConstantInt *C = dyn_cast<ConstantInt>(Op0)) {
|
|
|
|
// Replace (-1 - A) with (~A)...
|
2003-02-18 19:28:33 +00:00
|
|
|
if (C->isAllOnesValue())
|
|
|
|
return BinaryOperator::createNot(Op1);
|
|
|
|
|
2003-11-05 01:06:05 +00:00
|
|
|
// C - ~X == X + (1+C)
|
2005-06-18 17:37:34 +00:00
|
|
|
Value *X = 0;
|
2004-07-30 07:50:03 +00:00
|
|
|
if (match(Op1, m_Not(m_Value(X))))
|
|
|
|
return BinaryOperator::createAdd(X,
|
2004-06-10 02:07:29 +00:00
|
|
|
ConstantExpr::getAdd(C, ConstantInt::get(I.getType(), 1)));
|
2004-03-12 23:53:13 +00:00
|
|
|
// -((uint)X >> 31) -> ((int)X >> 31)
|
|
|
|
// -((int)X >> 31) -> ((uint)X >> 31)
|
2004-03-13 00:11:49 +00:00
|
|
|
if (C->isNullValue()) {
|
|
|
|
Value *NoopCastedRHS = RemoveNoopCast(Op1);
|
|
|
|
if (ShiftInst *SI = dyn_cast<ShiftInst>(NoopCastedRHS))
|
2004-03-12 23:53:13 +00:00
|
|
|
if (SI->getOpcode() == Instruction::Shr)
|
|
|
|
if (ConstantUInt *CU = dyn_cast<ConstantUInt>(SI->getOperand(1))) {
|
|
|
|
const Type *NewTy;
|
2004-03-13 00:11:49 +00:00
|
|
|
if (SI->getType()->isSigned())
|
2004-06-17 18:16:02 +00:00
|
|
|
NewTy = SI->getType()->getUnsignedVersion();
|
2004-03-12 23:53:13 +00:00
|
|
|
else
|
2004-06-17 18:16:02 +00:00
|
|
|
NewTy = SI->getType()->getSignedVersion();
|
2004-03-12 23:53:13 +00:00
|
|
|
// Check to see if we are shifting out everything but the sign bit.
|
2005-04-24 06:59:08 +00:00
|
|
|
if (CU->getValue() == SI->getType()->getPrimitiveSizeInBits()-1) {
|
2004-03-12 23:53:13 +00:00
|
|
|
// Ok, the transformation is safe. Insert a cast of the incoming
|
|
|
|
// value, then the new shift, then the new cast.
|
|
|
|
Instruction *FirstCast = new CastInst(SI->getOperand(0), NewTy,
|
|
|
|
SI->getOperand(0)->getName());
|
|
|
|
Value *InV = InsertNewInstBefore(FirstCast, I);
|
|
|
|
Instruction *NewShift = new ShiftInst(Instruction::Shr, FirstCast,
|
|
|
|
CU, SI->getName());
|
2004-03-13 00:11:49 +00:00
|
|
|
if (NewShift->getType() == I.getType())
|
|
|
|
return NewShift;
|
|
|
|
else {
|
|
|
|
InV = InsertNewInstBefore(NewShift, I);
|
|
|
|
return new CastInst(NewShift, I.getType());
|
|
|
|
}
|
2004-03-12 23:53:13 +00:00
|
|
|
}
|
|
|
|
}
|
2004-03-13 00:11:49 +00:00
|
|
|
}
|
2004-04-09 19:05:30 +00:00
|
|
|
|
|
|
|
// Try to fold constant sub into select arguments.
|
|
|
|
if (SelectInst *SI = dyn_cast<SelectInst>(Op1))
|
2005-01-01 16:22:27 +00:00
|
|
|
if (Instruction *R = FoldOpIntoSelect(I, SI, this))
|
2004-04-09 19:05:30 +00:00
|
|
|
return R;
|
Fold binary expressions and casts into PHI nodes that have all constant inputs.
This takes something like this:
%A = phi int [ 3, %cond_false.0 ], [ 2, %endif.0.i ], [ 2, %endif.1.i ]
%B = div int %tmp.243, 4
and turns it into:
%A = phi int [ 3/4, %cond_false.0 ], [ 2/4, %endif.0.i ], [ 2/4, %endif.1.i ]
which is later simplified (in this case) into %A = 0.
This triggers thousands of times in spec, for example, 269 times in 176.gcc.
This is tested by InstCombine/add.ll:test23 and set.ll:test18.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16582 91177308-0d34-0410-b5e6-96231b3b80d8
2004-09-29 05:07:12 +00:00
|
|
|
|
|
|
|
if (isa<PHINode>(Op0))
|
|
|
|
if (Instruction *NV = FoldOpIntoPhi(I))
|
|
|
|
return NV;
|
2003-11-05 01:06:05 +00:00
|
|
|
}
|
|
|
|
|
2005-04-07 16:15:25 +00:00
|
|
|
if (BinaryOperator *Op1I = dyn_cast<BinaryOperator>(Op1)) {
|
|
|
|
if (Op1I->getOpcode() == Instruction::Add &&
|
|
|
|
!Op0->getType()->isFloatingPoint()) {
|
2005-04-07 16:28:01 +00:00
|
|
|
if (Op1I->getOperand(0) == Op0) // X-(X+Y) == -Y
|
2005-04-07 16:15:25 +00:00
|
|
|
return BinaryOperator::createNeg(Op1I->getOperand(1), I.getName());
|
2005-04-07 16:28:01 +00:00
|
|
|
else if (Op1I->getOperand(1) == Op0) // X-(Y+X) == -Y
|
2005-04-07 16:15:25 +00:00
|
|
|
return BinaryOperator::createNeg(Op1I->getOperand(0), I.getName());
|
2005-04-07 16:28:01 +00:00
|
|
|
else if (ConstantInt *CI1 = dyn_cast<ConstantInt>(I.getOperand(0))) {
|
|
|
|
if (ConstantInt *CI2 = dyn_cast<ConstantInt>(Op1I->getOperand(1)))
|
|
|
|
// C1-(X+C2) --> (C1-C2)-X
|
|
|
|
return BinaryOperator::createSub(ConstantExpr::getSub(CI1, CI2),
|
|
|
|
Op1I->getOperand(0));
|
|
|
|
}
|
2005-04-07 16:15:25 +00:00
|
|
|
}
|
|
|
|
|
2003-10-15 16:48:29 +00:00
|
|
|
if (Op1I->hasOneUse()) {
|
2003-02-18 19:28:33 +00:00
|
|
|
// Replace (x - (y - z)) with (x + (z - y)) if the (y - z) subexpression
|
|
|
|
// is not used by anyone else...
|
|
|
|
//
|
2004-02-02 20:09:56 +00:00
|
|
|
if (Op1I->getOpcode() == Instruction::Sub &&
|
|
|
|
!Op1I->getType()->isFloatingPoint()) {
|
2003-02-18 19:28:33 +00:00
|
|
|
// Swap the two operands of the subexpr...
|
|
|
|
Value *IIOp0 = Op1I->getOperand(0), *IIOp1 = Op1I->getOperand(1);
|
|
|
|
Op1I->setOperand(0, IIOp1);
|
|
|
|
Op1I->setOperand(1, IIOp0);
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2003-02-18 19:28:33 +00:00
|
|
|
// Create the new top level add instruction...
|
2004-06-10 02:07:29 +00:00
|
|
|
return BinaryOperator::createAdd(Op0, Op1);
|
2003-02-18 19:28:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Replace (A - (A & B)) with (A & ~B) if this is the only use of (A&B)...
|
|
|
|
//
|
|
|
|
if (Op1I->getOpcode() == Instruction::And &&
|
|
|
|
(Op1I->getOperand(0) == Op0 || Op1I->getOperand(1) == Op0)) {
|
|
|
|
Value *OtherOp = Op1I->getOperand(Op1I->getOperand(0) == Op0);
|
|
|
|
|
Be more careful about the order we put stuff onto the worklist. This allow us to
collapse this:
bool %le(int %A, int %B) {
%c1 = setgt int %A, %B
%tmp = select bool %c1, int 1, int 0
%c2 = setlt int %A, %B
%result = select bool %c2, int -1, int %tmp
%c3 = setle int %result, 0
ret bool %c3
}
into:
bool %le(int %A, int %B) {
%c3 = setle int %A, %B ; <bool> [#uses=1]
ret bool %c3
}
which is handy, because the Java FE makes these sequences all over the place.
This is tested as: test/Regression/Transforms/InstCombine/JavaCompare.ll
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@14086 91177308-0d34-0410-b5e6-96231b3b80d8
2004-06-09 05:08:07 +00:00
|
|
|
Value *NewNot =
|
|
|
|
InsertNewInstBefore(BinaryOperator::createNot(OtherOp, "B.not"), I);
|
2004-06-10 02:07:29 +00:00
|
|
|
return BinaryOperator::createAnd(Op0, NewNot);
|
2003-02-18 19:28:33 +00:00
|
|
|
}
|
2003-02-18 19:57:07 +00:00
|
|
|
|
2004-10-06 15:08:25 +00:00
|
|
|
// -(X sdiv C) -> (X sdiv -C)
|
|
|
|
if (Op1I->getOpcode() == Instruction::Div)
|
|
|
|
if (ConstantSInt *CSI = dyn_cast<ConstantSInt>(Op0))
|
2005-04-07 16:15:25 +00:00
|
|
|
if (CSI->isNullValue())
|
2004-10-06 15:08:25 +00:00
|
|
|
if (Constant *DivRHS = dyn_cast<Constant>(Op1I->getOperand(1)))
|
2005-04-21 23:48:37 +00:00
|
|
|
return BinaryOperator::createDiv(Op1I->getOperand(0),
|
2004-10-06 15:08:25 +00:00
|
|
|
ConstantExpr::getNeg(DivRHS));
|
|
|
|
|
2003-02-18 19:57:07 +00:00
|
|
|
// X - X*C --> X * (1-C)
|
2005-06-18 17:37:34 +00:00
|
|
|
ConstantInt *C2 = 0;
|
2004-11-13 19:50:12 +00:00
|
|
|
if (dyn_castFoldableMul(Op1I, C2) == Op0) {
|
2005-04-21 23:48:37 +00:00
|
|
|
Constant *CP1 =
|
2004-11-13 19:50:12 +00:00
|
|
|
ConstantExpr::getSub(ConstantInt::get(I.getType(), 1), C2);
|
2004-06-10 02:07:29 +00:00
|
|
|
return BinaryOperator::createMul(Op0, CP1);
|
2003-02-18 19:57:07 +00:00
|
|
|
}
|
2002-05-09 01:29:19 +00:00
|
|
|
}
|
2005-04-07 16:15:25 +00:00
|
|
|
}
|
2003-02-18 19:28:33 +00:00
|
|
|
|
2005-04-07 17:14:51 +00:00
|
|
|
if (!Op0->getType()->isFloatingPoint())
|
|
|
|
if (BinaryOperator *Op0I = dyn_cast<BinaryOperator>(Op0))
|
|
|
|
if (Op0I->getOpcode() == Instruction::Add) {
|
2005-01-19 21:50:18 +00:00
|
|
|
if (Op0I->getOperand(0) == Op1) // (Y+X)-Y == X
|
|
|
|
return ReplaceInstUsesWith(I, Op0I->getOperand(1));
|
|
|
|
else if (Op0I->getOperand(1) == Op1) // (X+Y)-Y == X
|
|
|
|
return ReplaceInstUsesWith(I, Op0I->getOperand(0));
|
2005-04-07 17:14:51 +00:00
|
|
|
} else if (Op0I->getOpcode() == Instruction::Sub) {
|
|
|
|
if (Op0I->getOperand(0) == Op1) // (X-Y)-X == -Y
|
|
|
|
return BinaryOperator::createNeg(Op0I->getOperand(1), I.getName());
|
2005-01-19 21:50:18 +00:00
|
|
|
}
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2004-11-13 19:50:12 +00:00
|
|
|
ConstantInt *C1;
|
|
|
|
if (Value *X = dyn_castFoldableMul(Op0, C1)) {
|
|
|
|
if (X == Op1) { // X*C - X --> X * (C-1)
|
|
|
|
Constant *CP1 = ConstantExpr::getSub(C1, ConstantInt::get(I.getType(),1));
|
|
|
|
return BinaryOperator::createMul(Op1, CP1);
|
|
|
|
}
|
2003-02-18 19:57:07 +00:00
|
|
|
|
2004-11-13 19:50:12 +00:00
|
|
|
ConstantInt *C2; // X*C1 - X*C2 -> X * (C1-C2)
|
|
|
|
if (X == dyn_castFoldableMul(Op1, C2))
|
|
|
|
return BinaryOperator::createMul(Op1, ConstantExpr::getSub(C1, C2));
|
|
|
|
}
|
2002-05-06 16:14:14 +00:00
|
|
|
return 0;
|
2002-04-18 17:39:14 +00:00
|
|
|
}
|
|
|
|
|
2004-02-23 06:38:22 +00:00
|
|
|
/// isSignBitCheck - Given an exploded setcc instruction, return true if it is
|
|
|
|
/// really just returns true if the most significant (sign) bit is set.
|
|
|
|
static bool isSignBitCheck(unsigned Opcode, Value *LHS, ConstantInt *RHS) {
|
|
|
|
if (RHS->getType()->isSigned()) {
|
|
|
|
// True if source is LHS < 0 or LHS <= -1
|
|
|
|
return Opcode == Instruction::SetLT && RHS->isNullValue() ||
|
|
|
|
Opcode == Instruction::SetLE && RHS->isAllOnesValue();
|
|
|
|
} else {
|
|
|
|
ConstantUInt *RHSC = cast<ConstantUInt>(RHS);
|
|
|
|
// True if source is LHS > 127 or LHS >= 128, where the constants depend on
|
|
|
|
// the size of the integer type.
|
|
|
|
if (Opcode == Instruction::SetGE)
|
2005-04-24 06:59:08 +00:00
|
|
|
return RHSC->getValue() ==
|
|
|
|
1ULL << (RHS->getType()->getPrimitiveSizeInBits()-1);
|
2004-02-23 06:38:22 +00:00
|
|
|
if (Opcode == Instruction::SetGT)
|
|
|
|
return RHSC->getValue() ==
|
2005-04-24 06:59:08 +00:00
|
|
|
(1ULL << (RHS->getType()->getPrimitiveSizeInBits()-1))-1;
|
2004-02-23 06:38:22 +00:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2002-06-25 16:13:24 +00:00
|
|
|
Instruction *InstCombiner::visitMul(BinaryOperator &I) {
|
2003-03-10 21:43:22 +00:00
|
|
|
bool Changed = SimplifyCommutative(I);
|
2003-02-18 19:28:33 +00:00
|
|
|
Value *Op0 = I.getOperand(0);
|
2002-04-18 17:39:14 +00:00
|
|
|
|
2004-10-16 18:11:37 +00:00
|
|
|
if (isa<UndefValue>(I.getOperand(1))) // undef * X -> 0
|
|
|
|
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
|
|
|
|
|
2002-08-12 21:17:25 +00:00
|
|
|
// Simplify mul instructions with a constant RHS...
|
2003-02-18 19:28:33 +00:00
|
|
|
if (Constant *Op1 = dyn_cast<Constant>(I.getOperand(1))) {
|
|
|
|
if (ConstantInt *CI = dyn_cast<ConstantInt>(Op1)) {
|
2003-08-13 04:18:28 +00:00
|
|
|
|
|
|
|
// ((X << C1)*C2) == (X * (C2 << C1))
|
|
|
|
if (ShiftInst *SI = dyn_cast<ShiftInst>(Op0))
|
|
|
|
if (SI->getOpcode() == Instruction::Shl)
|
|
|
|
if (Constant *ShOp = dyn_cast<Constant>(SI->getOperand(1)))
|
2004-06-10 02:07:29 +00:00
|
|
|
return BinaryOperator::createMul(SI->getOperand(0),
|
|
|
|
ConstantExpr::getShl(CI, ShOp));
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2003-09-11 22:24:54 +00:00
|
|
|
if (CI->isNullValue())
|
|
|
|
return ReplaceInstUsesWith(I, Op1); // X * 0 == 0
|
|
|
|
if (CI->equalsInt(1)) // X * 1 == X
|
|
|
|
return ReplaceInstUsesWith(I, Op0);
|
|
|
|
if (CI->isAllOnesValue()) // X * -1 == 0 - X
|
2003-06-25 17:09:20 +00:00
|
|
|
return BinaryOperator::createNeg(Op0, I.getName());
|
2002-04-29 22:24:47 +00:00
|
|
|
|
2003-09-11 22:24:54 +00:00
|
|
|
int64_t Val = (int64_t)cast<ConstantInt>(CI)->getRawValue();
|
2005-08-02 19:16:58 +00:00
|
|
|
if (isPowerOf2_64(Val)) { // Replace X*(2^C) with X << C
|
|
|
|
uint64_t C = Log2_64(Val);
|
2003-02-18 19:28:33 +00:00
|
|
|
return new ShiftInst(Instruction::Shl, Op0,
|
|
|
|
ConstantUInt::get(Type::UByteTy, C));
|
2005-08-02 19:16:58 +00:00
|
|
|
}
|
2004-07-27 21:02:21 +00:00
|
|
|
} else if (ConstantFP *Op1F = dyn_cast<ConstantFP>(Op1)) {
|
2003-02-18 19:28:33 +00:00
|
|
|
if (Op1F->isNullValue())
|
|
|
|
return ReplaceInstUsesWith(I, Op1);
|
|
|
|
|
|
|
|
// "In IEEE floating point, x*1 is not equivalent to x for nans. However,
|
|
|
|
// ANSI says we can drop signals, so we can do this anyway." (from GCC)
|
|
|
|
if (Op1F->getValue() == 1.0)
|
|
|
|
return ReplaceInstUsesWith(I, Op0); // Eliminate 'mul double %X, 1.0'
|
|
|
|
}
|
2006-03-04 06:04:02 +00:00
|
|
|
|
|
|
|
if (BinaryOperator *Op0I = dyn_cast<BinaryOperator>(Op0))
|
|
|
|
if (Op0I->getOpcode() == Instruction::Add && Op0I->hasOneUse() &&
|
|
|
|
isa<ConstantInt>(Op0I->getOperand(1))) {
|
|
|
|
// Canonicalize (X+C1)*C2 -> X*C2+C1*C2.
|
|
|
|
Instruction *Add = BinaryOperator::createMul(Op0I->getOperand(0),
|
|
|
|
Op1, "tmp");
|
|
|
|
InsertNewInstBefore(Add, I);
|
|
|
|
Value *C1C2 = ConstantExpr::getMul(Op1,
|
|
|
|
cast<Constant>(Op0I->getOperand(1)));
|
|
|
|
return BinaryOperator::createAdd(Add, C1C2);
|
|
|
|
|
|
|
|
}
|
2004-04-09 19:05:30 +00:00
|
|
|
|
|
|
|
// Try to fold constant mul into select arguments.
|
|
|
|
if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
|
2005-01-01 16:22:27 +00:00
|
|
|
if (Instruction *R = FoldOpIntoSelect(I, SI, this))
|
2004-04-09 19:05:30 +00:00
|
|
|
return R;
|
Fold binary expressions and casts into PHI nodes that have all constant inputs.
This takes something like this:
%A = phi int [ 3, %cond_false.0 ], [ 2, %endif.0.i ], [ 2, %endif.1.i ]
%B = div int %tmp.243, 4
and turns it into:
%A = phi int [ 3/4, %cond_false.0 ], [ 2/4, %endif.0.i ], [ 2/4, %endif.1.i ]
which is later simplified (in this case) into %A = 0.
This triggers thousands of times in spec, for example, 269 times in 176.gcc.
This is tested by InstCombine/add.ll:test23 and set.ll:test18.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16582 91177308-0d34-0410-b5e6-96231b3b80d8
2004-09-29 05:07:12 +00:00
|
|
|
|
|
|
|
if (isa<PHINode>(Op0))
|
|
|
|
if (Instruction *NV = FoldOpIntoPhi(I))
|
|
|
|
return NV;
|
2001-12-14 16:52:21 +00:00
|
|
|
}
|
|
|
|
|
2003-03-10 23:23:04 +00:00
|
|
|
if (Value *Op0v = dyn_castNegVal(Op0)) // -X * -Y = X*Y
|
|
|
|
if (Value *Op1v = dyn_castNegVal(I.getOperand(1)))
|
2004-06-10 02:07:29 +00:00
|
|
|
return BinaryOperator::createMul(Op0v, Op1v);
|
2003-03-10 23:23:04 +00:00
|
|
|
|
2004-02-23 05:39:21 +00:00
|
|
|
// If one of the operands of the multiply is a cast from a boolean value, then
|
|
|
|
// we know the bool is either zero or one, so this is a 'masking' multiply.
|
|
|
|
// See if we can simplify things based on how the boolean was originally
|
|
|
|
// formed.
|
|
|
|
CastInst *BoolCast = 0;
|
|
|
|
if (CastInst *CI = dyn_cast<CastInst>(I.getOperand(0)))
|
|
|
|
if (CI->getOperand(0)->getType() == Type::BoolTy)
|
|
|
|
BoolCast = CI;
|
|
|
|
if (!BoolCast)
|
|
|
|
if (CastInst *CI = dyn_cast<CastInst>(I.getOperand(1)))
|
|
|
|
if (CI->getOperand(0)->getType() == Type::BoolTy)
|
|
|
|
BoolCast = CI;
|
|
|
|
if (BoolCast) {
|
|
|
|
if (SetCondInst *SCI = dyn_cast<SetCondInst>(BoolCast->getOperand(0))) {
|
|
|
|
Value *SCIOp0 = SCI->getOperand(0), *SCIOp1 = SCI->getOperand(1);
|
|
|
|
const Type *SCOpTy = SCIOp0->getType();
|
|
|
|
|
2004-02-23 06:38:22 +00:00
|
|
|
// If the setcc is true iff the sign bit of X is set, then convert this
|
|
|
|
// multiply into a shift/and combination.
|
|
|
|
if (isa<ConstantInt>(SCIOp1) &&
|
|
|
|
isSignBitCheck(SCI->getOpcode(), SCIOp0, cast<ConstantInt>(SCIOp1))) {
|
2004-02-23 05:39:21 +00:00
|
|
|
// Shift the X value right to turn it into "all signbits".
|
|
|
|
Constant *Amt = ConstantUInt::get(Type::UByteTy,
|
2005-04-24 06:59:08 +00:00
|
|
|
SCOpTy->getPrimitiveSizeInBits()-1);
|
2004-02-23 06:38:22 +00:00
|
|
|
if (SCIOp0->getType()->isUnsigned()) {
|
2004-06-17 18:16:02 +00:00
|
|
|
const Type *NewTy = SCIOp0->getType()->getSignedVersion();
|
2004-02-23 06:38:22 +00:00
|
|
|
SCIOp0 = InsertNewInstBefore(new CastInst(SCIOp0, NewTy,
|
|
|
|
SCIOp0->getName()), I);
|
|
|
|
}
|
|
|
|
|
|
|
|
Value *V =
|
|
|
|
InsertNewInstBefore(new ShiftInst(Instruction::Shr, SCIOp0, Amt,
|
|
|
|
BoolCast->getOperand(0)->getName()+
|
|
|
|
".mask"), I);
|
2004-02-23 05:39:21 +00:00
|
|
|
|
|
|
|
// If the multiply type is not the same as the source type, sign extend
|
|
|
|
// or truncate to the multiply type.
|
|
|
|
if (I.getType() != V->getType())
|
2004-02-23 06:38:22 +00:00
|
|
|
V = InsertNewInstBefore(new CastInst(V, I.getType(), V->getName()),I);
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2004-02-23 05:39:21 +00:00
|
|
|
Value *OtherOp = Op0 == BoolCast ? I.getOperand(1) : Op0;
|
2004-06-10 02:07:29 +00:00
|
|
|
return BinaryOperator::createAnd(V, OtherOp);
|
2004-02-23 05:39:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-06-25 16:13:24 +00:00
|
|
|
return Changed ? &I : 0;
|
2002-04-18 17:39:14 +00:00
|
|
|
}
|
|
|
|
|
2002-06-25 16:13:24 +00:00
|
|
|
Instruction *InstCombiner::visitDiv(BinaryOperator &I) {
|
2004-12-12 21:48:58 +00:00
|
|
|
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
|
|
|
|
|
|
|
if (isa<UndefValue>(Op0)) // undef / X -> 0
|
2004-10-16 18:11:37 +00:00
|
|
|
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
|
2004-12-12 21:48:58 +00:00
|
|
|
if (isa<UndefValue>(Op1))
|
|
|
|
return ReplaceInstUsesWith(I, Op1); // X / undef -> undef
|
2004-10-16 18:11:37 +00:00
|
|
|
|
2004-12-12 21:48:58 +00:00
|
|
|
if (ConstantInt *RHS = dyn_cast<ConstantInt>(Op1)) {
|
2004-04-26 14:01:59 +00:00
|
|
|
// div X, 1 == X
|
2002-08-12 21:17:25 +00:00
|
|
|
if (RHS->equalsInt(1))
|
2004-12-12 21:48:58 +00:00
|
|
|
return ReplaceInstUsesWith(I, Op0);
|
2003-02-18 19:28:33 +00:00
|
|
|
|
2004-04-26 14:01:59 +00:00
|
|
|
// div X, -1 == -X
|
|
|
|
if (RHS->isAllOnesValue())
|
2004-12-12 21:48:58 +00:00
|
|
|
return BinaryOperator::createNeg(Op0);
|
2004-04-26 14:01:59 +00:00
|
|
|
|
2004-12-12 21:48:58 +00:00
|
|
|
if (Instruction *LHS = dyn_cast<Instruction>(Op0))
|
2004-09-28 18:22:15 +00:00
|
|
|
if (LHS->getOpcode() == Instruction::Div)
|
|
|
|
if (ConstantInt *LHSRHS = dyn_cast<ConstantInt>(LHS->getOperand(1))) {
|
|
|
|
// (X / C1) / C2 -> X / (C1*C2)
|
|
|
|
return BinaryOperator::createDiv(LHS->getOperand(0),
|
|
|
|
ConstantExpr::getMul(RHS, LHSRHS));
|
|
|
|
}
|
|
|
|
|
2003-02-18 19:28:33 +00:00
|
|
|
// Check to see if this is an unsigned division with an exact power of 2,
|
|
|
|
// if so, convert to a right shift.
|
|
|
|
if (ConstantUInt *C = dyn_cast<ConstantUInt>(RHS))
|
|
|
|
if (uint64_t Val = C->getValue()) // Don't break X / 0
|
2005-08-02 19:16:58 +00:00
|
|
|
if (isPowerOf2_64(Val)) {
|
|
|
|
uint64_t C = Log2_64(Val);
|
2004-12-12 21:48:58 +00:00
|
|
|
return new ShiftInst(Instruction::Shr, Op0,
|
2003-02-18 19:28:33 +00:00
|
|
|
ConstantUInt::get(Type::UByteTy, C));
|
2005-08-02 19:16:58 +00:00
|
|
|
}
|
Fold binary expressions and casts into PHI nodes that have all constant inputs.
This takes something like this:
%A = phi int [ 3, %cond_false.0 ], [ 2, %endif.0.i ], [ 2, %endif.1.i ]
%B = div int %tmp.243, 4
and turns it into:
%A = phi int [ 3/4, %cond_false.0 ], [ 2/4, %endif.0.i ], [ 2/4, %endif.1.i ]
which is later simplified (in this case) into %A = 0.
This triggers thousands of times in spec, for example, 269 times in 176.gcc.
This is tested by InstCombine/add.ll:test23 and set.ll:test18.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16582 91177308-0d34-0410-b5e6-96231b3b80d8
2004-09-29 05:07:12 +00:00
|
|
|
|
2004-10-09 02:50:40 +00:00
|
|
|
// -X/C -> X/-C
|
|
|
|
if (RHS->getType()->isSigned())
|
2004-12-12 21:48:58 +00:00
|
|
|
if (Value *LHSNeg = dyn_castNegVal(Op0))
|
2004-10-09 02:50:40 +00:00
|
|
|
return BinaryOperator::createDiv(LHSNeg, ConstantExpr::getNeg(RHS));
|
|
|
|
|
2004-12-12 21:48:58 +00:00
|
|
|
if (!RHS->isNullValue()) {
|
|
|
|
if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
|
2005-01-01 16:22:27 +00:00
|
|
|
if (Instruction *R = FoldOpIntoSelect(I, SI, this))
|
2004-12-12 21:48:58 +00:00
|
|
|
return R;
|
|
|
|
if (isa<PHINode>(Op0))
|
|
|
|
if (Instruction *NV = FoldOpIntoPhi(I))
|
|
|
|
return NV;
|
|
|
|
}
|
2003-02-18 19:28:33 +00:00
|
|
|
}
|
|
|
|
|
2004-12-12 21:48:58 +00:00
|
|
|
// If this is 'udiv X, (Cond ? C1, C2)' where C1&C2 are powers of two,
|
|
|
|
// transform this into: '(Cond ? (udiv X, C1) : (udiv X, C2))'.
|
|
|
|
if (SelectInst *SI = dyn_cast<SelectInst>(Op1))
|
|
|
|
if (ConstantUInt *STO = dyn_cast<ConstantUInt>(SI->getOperand(1)))
|
|
|
|
if (ConstantUInt *SFO = dyn_cast<ConstantUInt>(SI->getOperand(2))) {
|
|
|
|
if (STO->getValue() == 0) { // Couldn't be this argument.
|
|
|
|
I.setOperand(1, SFO);
|
2005-04-21 23:48:37 +00:00
|
|
|
return &I;
|
2004-12-12 21:48:58 +00:00
|
|
|
} else if (SFO->getValue() == 0) {
|
2005-06-16 04:55:52 +00:00
|
|
|
I.setOperand(1, STO);
|
2005-04-21 23:48:37 +00:00
|
|
|
return &I;
|
2004-12-12 21:48:58 +00:00
|
|
|
}
|
|
|
|
|
2005-04-08 04:03:26 +00:00
|
|
|
uint64_t TVA = STO->getValue(), FVA = SFO->getValue();
|
2005-08-02 19:16:58 +00:00
|
|
|
if (isPowerOf2_64(TVA) && isPowerOf2_64(FVA)) {
|
|
|
|
unsigned TSA = Log2_64(TVA), FSA = Log2_64(FVA);
|
2005-04-08 04:03:26 +00:00
|
|
|
Constant *TC = ConstantUInt::get(Type::UByteTy, TSA);
|
|
|
|
Instruction *TSI = new ShiftInst(Instruction::Shr, Op0,
|
|
|
|
TC, SI->getName()+".t");
|
|
|
|
TSI = InsertNewInstBefore(TSI, I);
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2005-04-08 04:03:26 +00:00
|
|
|
Constant *FC = ConstantUInt::get(Type::UByteTy, FSA);
|
|
|
|
Instruction *FSI = new ShiftInst(Instruction::Shr, Op0,
|
|
|
|
FC, SI->getName()+".f");
|
|
|
|
FSI = InsertNewInstBefore(FSI, I);
|
|
|
|
return new SelectInst(SI->getOperand(0), TSI, FSI);
|
|
|
|
}
|
2004-12-12 21:48:58 +00:00
|
|
|
}
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2003-02-18 19:28:33 +00:00
|
|
|
// 0 / X == 0, we don't need to preserve faults!
|
2004-12-12 21:48:58 +00:00
|
|
|
if (ConstantInt *LHS = dyn_cast<ConstantInt>(Op0))
|
2003-02-18 19:28:33 +00:00
|
|
|
if (LHS->equalsInt(0))
|
|
|
|
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
|
|
|
|
|
2005-11-05 07:40:31 +00:00
|
|
|
if (I.getType()->isSigned()) {
|
2006-02-07 07:27:52 +00:00
|
|
|
// If the sign bits of both operands are zero (i.e. we can prove they are
|
2005-11-05 07:40:31 +00:00
|
|
|
// unsigned inputs), turn this into a udiv.
|
2006-02-07 07:27:52 +00:00
|
|
|
uint64_t Mask = 1ULL << (I.getType()->getPrimitiveSizeInBits()-1);
|
|
|
|
if (MaskedValueIsZero(Op1, Mask) && MaskedValueIsZero(Op0, Mask)) {
|
2005-11-05 07:40:31 +00:00
|
|
|
const Type *NTy = Op0->getType()->getUnsignedVersion();
|
|
|
|
Instruction *LHS = new CastInst(Op0, NTy, Op0->getName());
|
|
|
|
InsertNewInstBefore(LHS, I);
|
|
|
|
Value *RHS;
|
|
|
|
if (Constant *R = dyn_cast<Constant>(Op1))
|
|
|
|
RHS = ConstantExpr::getCast(R, NTy);
|
|
|
|
else
|
|
|
|
RHS = InsertNewInstBefore(new CastInst(Op1, NTy, Op1->getName()), I);
|
|
|
|
Instruction *Div = BinaryOperator::createDiv(LHS, RHS, I.getName());
|
|
|
|
InsertNewInstBefore(Div, I);
|
|
|
|
return new CastInst(Div, I.getType());
|
|
|
|
}
|
2006-02-05 07:54:04 +00:00
|
|
|
} else {
|
|
|
|
// Known to be an unsigned division.
|
|
|
|
if (Instruction *RHSI = dyn_cast<Instruction>(I.getOperand(1))) {
|
|
|
|
// Turn A / (C1 << N), where C1 is "1<<C2" into A >> (N+C2) [udiv only].
|
|
|
|
if (RHSI->getOpcode() == Instruction::Shl &&
|
|
|
|
isa<ConstantUInt>(RHSI->getOperand(0))) {
|
|
|
|
unsigned C1 = cast<ConstantUInt>(RHSI->getOperand(0))->getRawValue();
|
|
|
|
if (isPowerOf2_64(C1)) {
|
|
|
|
unsigned C2 = Log2_64(C1);
|
|
|
|
Value *Add = RHSI->getOperand(1);
|
|
|
|
if (C2) {
|
|
|
|
Constant *C2V = ConstantUInt::get(Add->getType(), C2);
|
|
|
|
Add = InsertNewInstBefore(BinaryOperator::createAdd(Add, C2V,
|
|
|
|
"tmp"), I);
|
|
|
|
}
|
|
|
|
return new ShiftInst(Instruction::Shr, Op0, Add);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2005-11-05 07:40:31 +00:00
|
|
|
}
|
|
|
|
|
2002-05-06 16:14:14 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-03-02 06:50:58 +00:00
|
|
|
/// GetFactor - If we can prove that the specified value is at least a multiple
|
|
|
|
/// of some factor, return that factor.
|
|
|
|
static Constant *GetFactor(Value *V) {
|
|
|
|
if (ConstantInt *CI = dyn_cast<ConstantInt>(V))
|
|
|
|
return CI;
|
|
|
|
|
|
|
|
// Unless we can be tricky, we know this is a multiple of 1.
|
|
|
|
Constant *Result = ConstantInt::get(V->getType(), 1);
|
|
|
|
|
|
|
|
Instruction *I = dyn_cast<Instruction>(V);
|
|
|
|
if (!I) return Result;
|
|
|
|
|
|
|
|
if (I->getOpcode() == Instruction::Mul) {
|
|
|
|
// Handle multiplies by a constant, etc.
|
|
|
|
return ConstantExpr::getMul(GetFactor(I->getOperand(0)),
|
|
|
|
GetFactor(I->getOperand(1)));
|
|
|
|
} else if (I->getOpcode() == Instruction::Shl) {
|
|
|
|
// (X<<C) -> X * (1 << C)
|
|
|
|
if (Constant *ShRHS = dyn_cast<Constant>(I->getOperand(1))) {
|
|
|
|
ShRHS = ConstantExpr::getShl(Result, ShRHS);
|
|
|
|
return ConstantExpr::getMul(GetFactor(I->getOperand(0)), ShRHS);
|
|
|
|
}
|
|
|
|
} else if (I->getOpcode() == Instruction::And) {
|
|
|
|
if (ConstantInt *RHS = dyn_cast<ConstantInt>(I->getOperand(1))) {
|
|
|
|
// X & 0xFFF0 is known to be a multiple of 16.
|
|
|
|
unsigned Zeros = CountTrailingZeros_64(RHS->getZExtValue());
|
|
|
|
if (Zeros != V->getType()->getPrimitiveSizeInBits())
|
|
|
|
return ConstantExpr::getShl(Result,
|
|
|
|
ConstantUInt::get(Type::UByteTy, Zeros));
|
|
|
|
}
|
|
|
|
} else if (I->getOpcode() == Instruction::Cast) {
|
|
|
|
Value *Op = I->getOperand(0);
|
|
|
|
// Only handle int->int casts.
|
|
|
|
if (!Op->getType()->isInteger()) return Result;
|
|
|
|
return ConstantExpr::getCast(GetFactor(Op), V->getType());
|
|
|
|
}
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2002-06-25 16:13:24 +00:00
|
|
|
Instruction *InstCombiner::visitRem(BinaryOperator &I) {
|
2004-12-12 21:48:58 +00:00
|
|
|
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
2006-02-28 05:30:45 +00:00
|
|
|
|
|
|
|
// 0 % X == 0, we don't need to preserve faults!
|
|
|
|
if (Constant *LHS = dyn_cast<Constant>(Op0))
|
|
|
|
if (LHS->isNullValue())
|
|
|
|
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
|
|
|
|
|
|
|
|
if (isa<UndefValue>(Op0)) // undef % X -> 0
|
|
|
|
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
|
|
|
|
if (isa<UndefValue>(Op1))
|
|
|
|
return ReplaceInstUsesWith(I, Op1); // X % undef -> undef
|
|
|
|
|
Turn srem -> urem when neither input has their sign bit set. This triggers
8 times in vortex, allowing the srems to be turned into shrs:
OLD: %tmp.104 = rem int %tmp.5.i37, 16 ; <int> [#uses=1]
NEW: %tmp.104 = rem uint %tmp.5.i37, 16 ; <uint> [#uses=0]
OLD: %tmp.98 = rem int %tmp.5.i24, 16 ; <int> [#uses=1]
NEW: %tmp.98 = rem uint %tmp.5.i24, 16 ; <uint> [#uses=0]
OLD: %tmp.91 = rem int %tmp.5.i19, 8 ; <int> [#uses=1]
NEW: %tmp.91 = rem uint %tmp.5.i19, 8 ; <uint> [#uses=0]
OLD: %tmp.88 = rem int %tmp.5.i14, 8 ; <int> [#uses=1]
NEW: %tmp.88 = rem uint %tmp.5.i14, 8 ; <uint> [#uses=0]
OLD: %tmp.85 = rem int %tmp.5.i9, 1024 ; <int> [#uses=2]
NEW: %tmp.85 = rem uint %tmp.5.i9, 1024 ; <uint> [#uses=0]
OLD: %tmp.82 = rem int %tmp.5.i, 512 ; <int> [#uses=2]
NEW: %tmp.82 = rem uint %tmp.5.i1, 512 ; <uint> [#uses=0]
OLD: %tmp.48.i = rem int %tmp.5.i.i161, 4 ; <int> [#uses=1]
NEW: %tmp.48.i = rem uint %tmp.5.i.i161, 4 ; <uint> [#uses=0]
OLD: %tmp.20.i2 = rem int %tmp.5.i.i, 4 ; <int> [#uses=1]
NEW: %tmp.20.i2 = rem uint %tmp.5.i.i, 4 ; <uint> [#uses=0]
it also occurs 9 times in gcc, but with odd constant divisors (1009 and 61)
so the payoff isn't as great.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@24189 91177308-0d34-0410-b5e6-96231b3b80d8
2005-11-05 07:28:37 +00:00
|
|
|
if (I.getType()->isSigned()) {
|
2004-12-12 21:48:58 +00:00
|
|
|
if (Value *RHSNeg = dyn_castNegVal(Op1))
|
2004-07-06 07:11:42 +00:00
|
|
|
if (!isa<ConstantSInt>(RHSNeg) ||
|
2004-08-09 21:05:48 +00:00
|
|
|
cast<ConstantSInt>(RHSNeg)->getValue() > 0) {
|
2004-07-06 07:01:22 +00:00
|
|
|
// X % -Y -> X % Y
|
|
|
|
AddUsesToWorkList(I);
|
|
|
|
I.setOperand(1, RHSNeg);
|
|
|
|
return &I;
|
|
|
|
}
|
Turn srem -> urem when neither input has their sign bit set. This triggers
8 times in vortex, allowing the srems to be turned into shrs:
OLD: %tmp.104 = rem int %tmp.5.i37, 16 ; <int> [#uses=1]
NEW: %tmp.104 = rem uint %tmp.5.i37, 16 ; <uint> [#uses=0]
OLD: %tmp.98 = rem int %tmp.5.i24, 16 ; <int> [#uses=1]
NEW: %tmp.98 = rem uint %tmp.5.i24, 16 ; <uint> [#uses=0]
OLD: %tmp.91 = rem int %tmp.5.i19, 8 ; <int> [#uses=1]
NEW: %tmp.91 = rem uint %tmp.5.i19, 8 ; <uint> [#uses=0]
OLD: %tmp.88 = rem int %tmp.5.i14, 8 ; <int> [#uses=1]
NEW: %tmp.88 = rem uint %tmp.5.i14, 8 ; <uint> [#uses=0]
OLD: %tmp.85 = rem int %tmp.5.i9, 1024 ; <int> [#uses=2]
NEW: %tmp.85 = rem uint %tmp.5.i9, 1024 ; <uint> [#uses=0]
OLD: %tmp.82 = rem int %tmp.5.i, 512 ; <int> [#uses=2]
NEW: %tmp.82 = rem uint %tmp.5.i1, 512 ; <uint> [#uses=0]
OLD: %tmp.48.i = rem int %tmp.5.i.i161, 4 ; <int> [#uses=1]
NEW: %tmp.48.i = rem uint %tmp.5.i.i161, 4 ; <uint> [#uses=0]
OLD: %tmp.20.i2 = rem int %tmp.5.i.i, 4 ; <int> [#uses=1]
NEW: %tmp.20.i2 = rem uint %tmp.5.i.i, 4 ; <uint> [#uses=0]
it also occurs 9 times in gcc, but with odd constant divisors (1009 and 61)
so the payoff isn't as great.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@24189 91177308-0d34-0410-b5e6-96231b3b80d8
2005-11-05 07:28:37 +00:00
|
|
|
|
|
|
|
// If the top bits of both operands are zero (i.e. we can prove they are
|
|
|
|
// unsigned inputs), turn this into a urem.
|
2006-02-07 07:27:52 +00:00
|
|
|
uint64_t Mask = 1ULL << (I.getType()->getPrimitiveSizeInBits()-1);
|
|
|
|
if (MaskedValueIsZero(Op1, Mask) && MaskedValueIsZero(Op0, Mask)) {
|
Turn srem -> urem when neither input has their sign bit set. This triggers
8 times in vortex, allowing the srems to be turned into shrs:
OLD: %tmp.104 = rem int %tmp.5.i37, 16 ; <int> [#uses=1]
NEW: %tmp.104 = rem uint %tmp.5.i37, 16 ; <uint> [#uses=0]
OLD: %tmp.98 = rem int %tmp.5.i24, 16 ; <int> [#uses=1]
NEW: %tmp.98 = rem uint %tmp.5.i24, 16 ; <uint> [#uses=0]
OLD: %tmp.91 = rem int %tmp.5.i19, 8 ; <int> [#uses=1]
NEW: %tmp.91 = rem uint %tmp.5.i19, 8 ; <uint> [#uses=0]
OLD: %tmp.88 = rem int %tmp.5.i14, 8 ; <int> [#uses=1]
NEW: %tmp.88 = rem uint %tmp.5.i14, 8 ; <uint> [#uses=0]
OLD: %tmp.85 = rem int %tmp.5.i9, 1024 ; <int> [#uses=2]
NEW: %tmp.85 = rem uint %tmp.5.i9, 1024 ; <uint> [#uses=0]
OLD: %tmp.82 = rem int %tmp.5.i, 512 ; <int> [#uses=2]
NEW: %tmp.82 = rem uint %tmp.5.i1, 512 ; <uint> [#uses=0]
OLD: %tmp.48.i = rem int %tmp.5.i.i161, 4 ; <int> [#uses=1]
NEW: %tmp.48.i = rem uint %tmp.5.i.i161, 4 ; <uint> [#uses=0]
OLD: %tmp.20.i2 = rem int %tmp.5.i.i, 4 ; <int> [#uses=1]
NEW: %tmp.20.i2 = rem uint %tmp.5.i.i, 4 ; <uint> [#uses=0]
it also occurs 9 times in gcc, but with odd constant divisors (1009 and 61)
so the payoff isn't as great.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@24189 91177308-0d34-0410-b5e6-96231b3b80d8
2005-11-05 07:28:37 +00:00
|
|
|
const Type *NTy = Op0->getType()->getUnsignedVersion();
|
|
|
|
Instruction *LHS = new CastInst(Op0, NTy, Op0->getName());
|
|
|
|
InsertNewInstBefore(LHS, I);
|
|
|
|
Value *RHS;
|
|
|
|
if (Constant *R = dyn_cast<Constant>(Op1))
|
|
|
|
RHS = ConstantExpr::getCast(R, NTy);
|
|
|
|
else
|
|
|
|
RHS = InsertNewInstBefore(new CastInst(Op1, NTy, Op1->getName()), I);
|
|
|
|
Instruction *Rem = BinaryOperator::createRem(LHS, RHS, I.getName());
|
|
|
|
InsertNewInstBefore(Rem, I);
|
|
|
|
return new CastInst(Rem, I.getType());
|
|
|
|
}
|
|
|
|
}
|
2004-07-06 07:01:22 +00:00
|
|
|
|
2004-12-12 21:48:58 +00:00
|
|
|
if (ConstantInt *RHS = dyn_cast<ConstantInt>(Op1)) {
|
2006-02-28 05:30:45 +00:00
|
|
|
// X % 0 == undef, we don't need to preserve faults!
|
|
|
|
if (RHS->equalsInt(0))
|
|
|
|
return ReplaceInstUsesWith(I, UndefValue::get(I.getType()));
|
|
|
|
|
2003-02-18 19:28:33 +00:00
|
|
|
if (RHS->equalsInt(1)) // X % 1 == 0
|
|
|
|
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
|
|
|
|
|
|
|
|
// Check to see if this is an unsigned remainder with an exact power of 2,
|
|
|
|
// if so, convert to a bitwise and.
|
|
|
|
if (ConstantUInt *C = dyn_cast<ConstantUInt>(RHS))
|
2006-02-28 05:30:45 +00:00
|
|
|
if (isPowerOf2_64(C->getValue()))
|
|
|
|
return BinaryOperator::createAnd(Op0, SubOne(C));
|
2004-12-12 21:48:58 +00:00
|
|
|
|
2006-02-28 05:49:21 +00:00
|
|
|
if (Instruction *Op0I = dyn_cast<Instruction>(Op0)) {
|
|
|
|
if (SelectInst *SI = dyn_cast<SelectInst>(Op0I)) {
|
|
|
|
if (Instruction *R = FoldOpIntoSelect(I, SI, this))
|
|
|
|
return R;
|
|
|
|
} else if (isa<PHINode>(Op0I)) {
|
|
|
|
if (Instruction *NV = FoldOpIntoPhi(I))
|
|
|
|
return NV;
|
|
|
|
}
|
2006-03-02 06:50:58 +00:00
|
|
|
|
|
|
|
// X*C1%C2 --> 0 iff C1%C2 == 0
|
|
|
|
if (ConstantExpr::getRem(GetFactor(Op0I), RHS)->isNullValue())
|
|
|
|
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
|
2006-02-28 05:49:21 +00:00
|
|
|
}
|
2003-02-18 19:28:33 +00:00
|
|
|
}
|
|
|
|
|
2006-02-05 07:54:04 +00:00
|
|
|
if (Instruction *RHSI = dyn_cast<Instruction>(I.getOperand(1))) {
|
|
|
|
// Turn A % (C << N), where C is 2^k, into A & ((C << N)-1) [urem only].
|
|
|
|
if (I.getType()->isUnsigned() &&
|
|
|
|
RHSI->getOpcode() == Instruction::Shl &&
|
|
|
|
isa<ConstantUInt>(RHSI->getOperand(0))) {
|
|
|
|
unsigned C1 = cast<ConstantUInt>(RHSI->getOperand(0))->getRawValue();
|
|
|
|
if (isPowerOf2_64(C1)) {
|
|
|
|
Constant *N1 = ConstantInt::getAllOnesValue(I.getType());
|
|
|
|
Value *Add = InsertNewInstBefore(BinaryOperator::createAdd(RHSI, N1,
|
|
|
|
"tmp"), I);
|
|
|
|
return BinaryOperator::createAnd(Op0, Add);
|
|
|
|
}
|
|
|
|
}
|
2006-02-28 05:30:45 +00:00
|
|
|
|
|
|
|
// If this is 'urem X, (Cond ? C1, C2)' where C1&C2 are powers of two,
|
|
|
|
// transform this into: '(Cond ? (urem X, C1) : (urem X, C2))'.
|
|
|
|
if (SelectInst *SI = dyn_cast<SelectInst>(Op1))
|
|
|
|
if (ConstantUInt *STO = dyn_cast<ConstantUInt>(SI->getOperand(1)))
|
|
|
|
if (ConstantUInt *SFO = dyn_cast<ConstantUInt>(SI->getOperand(2))) {
|
|
|
|
if (STO->getValue() == 0) { // Couldn't be this argument.
|
|
|
|
I.setOperand(1, SFO);
|
|
|
|
return &I;
|
|
|
|
} else if (SFO->getValue() == 0) {
|
|
|
|
I.setOperand(1, STO);
|
|
|
|
return &I;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isPowerOf2_64(STO->getValue()) && isPowerOf2_64(SFO->getValue())){
|
|
|
|
Value *TrueAnd = InsertNewInstBefore(BinaryOperator::createAnd(Op0,
|
|
|
|
SubOne(STO), SI->getName()+".t"), I);
|
|
|
|
Value *FalseAnd = InsertNewInstBefore(BinaryOperator::createAnd(Op0,
|
|
|
|
SubOne(SFO), SI->getName()+".f"), I);
|
|
|
|
return new SelectInst(SI->getOperand(0), TrueAnd, FalseAnd);
|
|
|
|
}
|
|
|
|
}
|
2006-02-05 07:54:04 +00:00
|
|
|
}
|
|
|
|
|
2002-08-12 21:17:25 +00:00
|
|
|
return 0;
|
2002-08-09 23:47:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// isMaxValueMinusOne - return true if this is Max-1
|
2002-08-12 21:17:25 +00:00
|
|
|
static bool isMaxValueMinusOne(const ConstantInt *C) {
|
2006-02-07 07:00:41 +00:00
|
|
|
if (const ConstantUInt *CU = dyn_cast<ConstantUInt>(C))
|
|
|
|
return CU->getValue() == C->getType()->getIntegralTypeMask()-1;
|
2002-08-09 23:47:40 +00:00
|
|
|
|
|
|
|
const ConstantSInt *CS = cast<ConstantSInt>(C);
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2002-08-09 23:47:40 +00:00
|
|
|
// Calculate 0111111111..11111
|
2005-04-24 06:59:08 +00:00
|
|
|
unsigned TypeBits = C->getType()->getPrimitiveSizeInBits();
|
2002-08-09 23:47:40 +00:00
|
|
|
int64_t Val = INT64_MAX; // All ones
|
|
|
|
Val >>= 64-TypeBits; // Shift out unwanted 1 bits...
|
|
|
|
return CS->getValue() == Val-1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// isMinValuePlusOne - return true if this is Min+1
|
2002-08-12 21:17:25 +00:00
|
|
|
static bool isMinValuePlusOne(const ConstantInt *C) {
|
2002-08-09 23:47:40 +00:00
|
|
|
if (const ConstantUInt *CU = dyn_cast<ConstantUInt>(C))
|
|
|
|
return CU->getValue() == 1;
|
|
|
|
|
|
|
|
const ConstantSInt *CS = cast<ConstantSInt>(C);
|
2005-04-21 23:48:37 +00:00
|
|
|
|
|
|
|
// Calculate 1111111111000000000000
|
2005-04-24 06:59:08 +00:00
|
|
|
unsigned TypeBits = C->getType()->getPrimitiveSizeInBits();
|
2002-08-09 23:47:40 +00:00
|
|
|
int64_t Val = -1; // All ones
|
|
|
|
Val <<= TypeBits-1; // Shift over to the right spot
|
|
|
|
return CS->getValue() == Val+1;
|
2002-05-06 16:14:14 +00:00
|
|
|
}
|
|
|
|
|
2004-06-09 07:59:58 +00:00
|
|
|
// isOneBitSet - Return true if there is exactly one bit set in the specified
|
|
|
|
// constant.
|
|
|
|
static bool isOneBitSet(const ConstantInt *CI) {
|
|
|
|
uint64_t V = CI->getRawValue();
|
|
|
|
return V && (V & (V-1)) == 0;
|
|
|
|
}
|
|
|
|
|
2004-09-23 21:46:38 +00:00
|
|
|
#if 0 // Currently unused
|
|
|
|
// isLowOnes - Return true if the constant is of the form 0+1+.
|
|
|
|
static bool isLowOnes(const ConstantInt *CI) {
|
|
|
|
uint64_t V = CI->getRawValue();
|
|
|
|
|
|
|
|
// There won't be bits set in parts that the type doesn't contain.
|
|
|
|
V &= ConstantInt::getAllOnesValue(CI->getType())->getRawValue();
|
|
|
|
|
|
|
|
uint64_t U = V+1; // If it is low ones, this should be a power of two.
|
|
|
|
return U && V && (U & V) == 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// isHighOnes - Return true if the constant is of the form 1+0+.
|
|
|
|
// This is the same as lowones(~X).
|
|
|
|
static bool isHighOnes(const ConstantInt *CI) {
|
|
|
|
uint64_t V = ~CI->getRawValue();
|
2005-08-07 07:03:10 +00:00
|
|
|
if (~V == 0) return false; // 0's does not match "1+"
|
2004-09-23 21:46:38 +00:00
|
|
|
|
|
|
|
// There won't be bits set in parts that the type doesn't contain.
|
|
|
|
V &= ConstantInt::getAllOnesValue(CI->getType())->getRawValue();
|
|
|
|
|
|
|
|
uint64_t U = V+1; // If it is low ones, this should be a power of two.
|
|
|
|
return U && V && (U & V) == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-08-13 20:16:26 +00:00
|
|
|
/// getSetCondCode - Encode a setcc opcode into a three bit mask. These bits
|
|
|
|
/// are carefully arranged to allow folding of expressions such as:
|
|
|
|
///
|
|
|
|
/// (A < B) | (A > B) --> (A != B)
|
|
|
|
///
|
|
|
|
/// Bit value '4' represents that the comparison is true if A > B, bit value '2'
|
|
|
|
/// represents that the comparison is true if A == B, and bit value '1' is true
|
|
|
|
/// if A < B.
|
|
|
|
///
|
|
|
|
static unsigned getSetCondCode(const SetCondInst *SCI) {
|
|
|
|
switch (SCI->getOpcode()) {
|
|
|
|
// False -> 0
|
|
|
|
case Instruction::SetGT: return 1;
|
|
|
|
case Instruction::SetEQ: return 2;
|
|
|
|
case Instruction::SetGE: return 3;
|
|
|
|
case Instruction::SetLT: return 4;
|
|
|
|
case Instruction::SetNE: return 5;
|
|
|
|
case Instruction::SetLE: return 6;
|
|
|
|
// True -> 7
|
|
|
|
default:
|
|
|
|
assert(0 && "Invalid SetCC opcode!");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// getSetCCValue - This is the complement of getSetCondCode, which turns an
|
|
|
|
/// opcode and two operands into either a constant true or false, or a brand new
|
|
|
|
/// SetCC instruction.
|
|
|
|
static Value *getSetCCValue(unsigned Opcode, Value *LHS, Value *RHS) {
|
|
|
|
switch (Opcode) {
|
|
|
|
case 0: return ConstantBool::False;
|
|
|
|
case 1: return new SetCondInst(Instruction::SetGT, LHS, RHS);
|
|
|
|
case 2: return new SetCondInst(Instruction::SetEQ, LHS, RHS);
|
|
|
|
case 3: return new SetCondInst(Instruction::SetGE, LHS, RHS);
|
|
|
|
case 4: return new SetCondInst(Instruction::SetLT, LHS, RHS);
|
|
|
|
case 5: return new SetCondInst(Instruction::SetNE, LHS, RHS);
|
|
|
|
case 6: return new SetCondInst(Instruction::SetLE, LHS, RHS);
|
|
|
|
case 7: return ConstantBool::True;
|
|
|
|
default: assert(0 && "Illegal SetCCCode!"); return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// FoldSetCCLogical - Implements (setcc1 A, B) & (setcc2 A, B) --> (setcc3 A, B)
|
|
|
|
struct FoldSetCCLogical {
|
|
|
|
InstCombiner &IC;
|
|
|
|
Value *LHS, *RHS;
|
|
|
|
FoldSetCCLogical(InstCombiner &ic, SetCondInst *SCI)
|
|
|
|
: IC(ic), LHS(SCI->getOperand(0)), RHS(SCI->getOperand(1)) {}
|
|
|
|
bool shouldApply(Value *V) const {
|
|
|
|
if (SetCondInst *SCI = dyn_cast<SetCondInst>(V))
|
|
|
|
return (SCI->getOperand(0) == LHS && SCI->getOperand(1) == RHS ||
|
|
|
|
SCI->getOperand(0) == RHS && SCI->getOperand(1) == LHS);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
Instruction *apply(BinaryOperator &Log) const {
|
|
|
|
SetCondInst *SCI = cast<SetCondInst>(Log.getOperand(0));
|
|
|
|
if (SCI->getOperand(0) != LHS) {
|
|
|
|
assert(SCI->getOperand(1) == LHS);
|
|
|
|
SCI->swapOperands(); // Swap the LHS and RHS of the SetCC
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned LHSCode = getSetCondCode(SCI);
|
|
|
|
unsigned RHSCode = getSetCondCode(cast<SetCondInst>(Log.getOperand(1)));
|
|
|
|
unsigned Code;
|
|
|
|
switch (Log.getOpcode()) {
|
|
|
|
case Instruction::And: Code = LHSCode & RHSCode; break;
|
|
|
|
case Instruction::Or: Code = LHSCode | RHSCode; break;
|
|
|
|
case Instruction::Xor: Code = LHSCode ^ RHSCode; break;
|
2003-09-22 20:33:34 +00:00
|
|
|
default: assert(0 && "Illegal logical opcode!"); return 0;
|
2003-08-13 20:16:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Value *RV = getSetCCValue(Code, LHS, RHS);
|
|
|
|
if (Instruction *I = dyn_cast<Instruction>(RV))
|
|
|
|
return I;
|
|
|
|
// Otherwise, it's a constant boolean value...
|
|
|
|
return IC.ReplaceInstUsesWith(Log, RV);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2003-09-19 17:17:26 +00:00
|
|
|
// OptAndOp - This handles expressions of the form ((val OP C1) & C2). Where
|
|
|
|
// the Op parameter is 'OP', OpRHS is 'C1', and AndRHS is 'C2'. Op is
|
|
|
|
// guaranteed to be either a shift instruction or a binary operator.
|
|
|
|
Instruction *InstCombiner::OptAndOp(Instruction *Op,
|
|
|
|
ConstantIntegral *OpRHS,
|
|
|
|
ConstantIntegral *AndRHS,
|
|
|
|
BinaryOperator &TheAnd) {
|
|
|
|
Value *X = Op->getOperand(0);
|
2004-01-12 19:47:05 +00:00
|
|
|
Constant *Together = 0;
|
|
|
|
if (!isa<ShiftInst>(Op))
|
2004-06-10 02:07:29 +00:00
|
|
|
Together = ConstantExpr::getAnd(AndRHS, OpRHS);
|
2004-01-12 19:35:11 +00:00
|
|
|
|
2003-09-19 17:17:26 +00:00
|
|
|
switch (Op->getOpcode()) {
|
|
|
|
case Instruction::Xor:
|
2005-01-01 16:22:27 +00:00
|
|
|
if (Op->hasOneUse()) {
|
2003-09-19 17:17:26 +00:00
|
|
|
// (X ^ C1) & C2 --> (X & C2) ^ (C1&C2)
|
|
|
|
std::string OpName = Op->getName(); Op->setName("");
|
2004-06-10 02:07:29 +00:00
|
|
|
Instruction *And = BinaryOperator::createAnd(X, AndRHS, OpName);
|
2003-09-19 17:17:26 +00:00
|
|
|
InsertNewInstBefore(And, TheAnd);
|
2004-06-10 02:07:29 +00:00
|
|
|
return BinaryOperator::createXor(And, Together);
|
2003-09-19 17:17:26 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case Instruction::Or:
|
2005-01-01 16:22:27 +00:00
|
|
|
if (Together == AndRHS) // (X | C) & C --> C
|
|
|
|
return ReplaceInstUsesWith(TheAnd, AndRHS);
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2005-01-01 16:22:27 +00:00
|
|
|
if (Op->hasOneUse() && Together != OpRHS) {
|
|
|
|
// (X | C1) & C2 --> (X | (C1&C2)) & C2
|
|
|
|
std::string Op0Name = Op->getName(); Op->setName("");
|
|
|
|
Instruction *Or = BinaryOperator::createOr(X, Together, Op0Name);
|
|
|
|
InsertNewInstBefore(Or, TheAnd);
|
|
|
|
return BinaryOperator::createAnd(Or, AndRHS);
|
2003-09-19 17:17:26 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case Instruction::Add:
|
2003-10-15 16:48:29 +00:00
|
|
|
if (Op->hasOneUse()) {
|
2003-09-19 17:17:26 +00:00
|
|
|
// Adding a one to a single bit bit-field should be turned into an XOR
|
|
|
|
// of the bit. First thing to check is to see if this AND is with a
|
|
|
|
// single bit constant.
|
2004-06-09 07:59:58 +00:00
|
|
|
uint64_t AndRHSV = cast<ConstantInt>(AndRHS)->getRawValue();
|
2003-09-19 17:17:26 +00:00
|
|
|
|
|
|
|
// Clear bits that are not part of the constant.
|
2006-02-07 07:00:41 +00:00
|
|
|
AndRHSV &= AndRHS->getType()->getIntegralTypeMask();
|
2003-09-19 17:17:26 +00:00
|
|
|
|
|
|
|
// If there is only one bit set...
|
2004-06-09 07:59:58 +00:00
|
|
|
if (isOneBitSet(cast<ConstantInt>(AndRHS))) {
|
2003-09-19 17:17:26 +00:00
|
|
|
// Ok, at this point, we know that we are masking the result of the
|
|
|
|
// ADD down to exactly one bit. If the constant we are adding has
|
|
|
|
// no bits set below this bit, then we can eliminate the ADD.
|
2004-06-09 07:59:58 +00:00
|
|
|
uint64_t AddRHS = cast<ConstantInt>(OpRHS)->getRawValue();
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2003-09-19 17:17:26 +00:00
|
|
|
// Check to see if any bits below the one bit set in AndRHSV are set.
|
|
|
|
if ((AddRHS & (AndRHSV-1)) == 0) {
|
|
|
|
// If not, the only thing that can effect the output of the AND is
|
|
|
|
// the bit specified by AndRHSV. If that bit is set, the effect of
|
|
|
|
// the XOR is to toggle the bit. If it is clear, then the ADD has
|
|
|
|
// no effect.
|
|
|
|
if ((AddRHS & AndRHSV) == 0) { // Bit is not set, noop
|
|
|
|
TheAnd.setOperand(0, X);
|
|
|
|
return &TheAnd;
|
|
|
|
} else {
|
|
|
|
std::string Name = Op->getName(); Op->setName("");
|
|
|
|
// Pull the XOR out of the AND.
|
2004-06-10 02:07:29 +00:00
|
|
|
Instruction *NewAnd = BinaryOperator::createAnd(X, AndRHS, Name);
|
2003-09-19 17:17:26 +00:00
|
|
|
InsertNewInstBefore(NewAnd, TheAnd);
|
2004-06-10 02:07:29 +00:00
|
|
|
return BinaryOperator::createXor(NewAnd, AndRHS);
|
2003-09-19 17:17:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2003-09-19 19:05:02 +00:00
|
|
|
|
|
|
|
case Instruction::Shl: {
|
|
|
|
// We know that the AND will not produce any of the bits shifted in, so if
|
|
|
|
// the anded constant includes them, clear them now!
|
|
|
|
//
|
|
|
|
Constant *AllOne = ConstantIntegral::getAllOnesValue(AndRHS->getType());
|
2004-09-24 15:21:34 +00:00
|
|
|
Constant *ShlMask = ConstantExpr::getShl(AllOne, OpRHS);
|
|
|
|
Constant *CI = ConstantExpr::getAnd(AndRHS, ShlMask);
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2004-09-24 15:21:34 +00:00
|
|
|
if (CI == ShlMask) { // Masking out bits that the shift already masks
|
|
|
|
return ReplaceInstUsesWith(TheAnd, Op); // No need for the and.
|
|
|
|
} else if (CI != AndRHS) { // Reducing bits set in and.
|
2003-09-19 19:05:02 +00:00
|
|
|
TheAnd.setOperand(1, CI);
|
|
|
|
return &TheAnd;
|
|
|
|
}
|
|
|
|
break;
|
2005-04-21 23:48:37 +00:00
|
|
|
}
|
2003-09-19 19:05:02 +00:00
|
|
|
case Instruction::Shr:
|
|
|
|
// We know that the AND will not produce any of the bits shifted in, so if
|
|
|
|
// the anded constant includes them, clear them now! This only applies to
|
|
|
|
// unsigned shifts, because a signed shr may bring in set bits!
|
|
|
|
//
|
|
|
|
if (AndRHS->getType()->isUnsigned()) {
|
|
|
|
Constant *AllOne = ConstantIntegral::getAllOnesValue(AndRHS->getType());
|
2004-09-24 15:21:34 +00:00
|
|
|
Constant *ShrMask = ConstantExpr::getShr(AllOne, OpRHS);
|
|
|
|
Constant *CI = ConstantExpr::getAnd(AndRHS, ShrMask);
|
|
|
|
|
|
|
|
if (CI == ShrMask) { // Masking out bits that the shift already masks.
|
|
|
|
return ReplaceInstUsesWith(TheAnd, Op);
|
|
|
|
} else if (CI != AndRHS) {
|
|
|
|
TheAnd.setOperand(1, CI); // Reduce bits set in and cst.
|
2003-09-19 19:05:02 +00:00
|
|
|
return &TheAnd;
|
|
|
|
}
|
2004-09-24 15:21:34 +00:00
|
|
|
} else { // Signed shr.
|
|
|
|
// See if this is shifting in some sign extension, then masking it out
|
|
|
|
// with an and.
|
|
|
|
if (Op->hasOneUse()) {
|
|
|
|
Constant *AllOne = ConstantIntegral::getAllOnesValue(AndRHS->getType());
|
|
|
|
Constant *ShrMask = ConstantExpr::getUShr(AllOne, OpRHS);
|
|
|
|
Constant *CI = ConstantExpr::getAnd(AndRHS, ShrMask);
|
2004-10-22 04:53:16 +00:00
|
|
|
if (CI == AndRHS) { // Masking out bits shifted in.
|
2004-09-24 15:21:34 +00:00
|
|
|
// Make the argument unsigned.
|
|
|
|
Value *ShVal = Op->getOperand(0);
|
|
|
|
ShVal = InsertCastBefore(ShVal,
|
|
|
|
ShVal->getType()->getUnsignedVersion(),
|
|
|
|
TheAnd);
|
|
|
|
ShVal = InsertNewInstBefore(new ShiftInst(Instruction::Shr, ShVal,
|
|
|
|
OpRHS, Op->getName()),
|
|
|
|
TheAnd);
|
2004-10-27 05:57:15 +00:00
|
|
|
Value *AndRHS2 = ConstantExpr::getCast(AndRHS, ShVal->getType());
|
|
|
|
ShVal = InsertNewInstBefore(BinaryOperator::createAnd(ShVal, AndRHS2,
|
|
|
|
TheAnd.getName()),
|
|
|
|
TheAnd);
|
2004-09-24 15:21:34 +00:00
|
|
|
return new CastInst(ShVal, Op->getType());
|
|
|
|
}
|
|
|
|
}
|
2003-09-19 19:05:02 +00:00
|
|
|
}
|
|
|
|
break;
|
2003-09-19 17:17:26 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2002-05-06 16:14:14 +00:00
|
|
|
|
2004-09-29 17:40:11 +00:00
|
|
|
/// InsertRangeTest - Emit a computation of: (V >= Lo && V < Hi) if Inside is
|
|
|
|
/// true, otherwise (V < Lo || V >= Hi). In pratice, we emit the more efficient
|
|
|
|
/// (V-Lo) <u Hi-Lo. This method expects that Lo <= Hi. IB is the location to
|
|
|
|
/// insert new instructions.
|
|
|
|
Instruction *InstCombiner::InsertRangeTest(Value *V, Constant *Lo, Constant *Hi,
|
|
|
|
bool Inside, Instruction &IB) {
|
|
|
|
assert(cast<ConstantBool>(ConstantExpr::getSetLE(Lo, Hi))->getValue() &&
|
|
|
|
"Lo is not <= Hi in range emission code!");
|
|
|
|
if (Inside) {
|
|
|
|
if (Lo == Hi) // Trivially false.
|
|
|
|
return new SetCondInst(Instruction::SetNE, V, V);
|
|
|
|
if (cast<ConstantIntegral>(Lo)->isMinValue())
|
|
|
|
return new SetCondInst(Instruction::SetLT, V, Hi);
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2004-09-29 17:40:11 +00:00
|
|
|
Constant *AddCST = ConstantExpr::getNeg(Lo);
|
|
|
|
Instruction *Add = BinaryOperator::createAdd(V, AddCST,V->getName()+".off");
|
|
|
|
InsertNewInstBefore(Add, IB);
|
|
|
|
// Convert to unsigned for the comparison.
|
|
|
|
const Type *UnsType = Add->getType()->getUnsignedVersion();
|
|
|
|
Value *OffsetVal = InsertCastBefore(Add, UnsType, IB);
|
|
|
|
AddCST = ConstantExpr::getAdd(AddCST, Hi);
|
|
|
|
AddCST = ConstantExpr::getCast(AddCST, UnsType);
|
|
|
|
return new SetCondInst(Instruction::SetLT, OffsetVal, AddCST);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Lo == Hi) // Trivially true.
|
|
|
|
return new SetCondInst(Instruction::SetEQ, V, V);
|
|
|
|
|
|
|
|
Hi = SubOne(cast<ConstantInt>(Hi));
|
|
|
|
if (cast<ConstantIntegral>(Lo)->isMinValue()) // V < 0 || V >= Hi ->'V > Hi-1'
|
|
|
|
return new SetCondInst(Instruction::SetGT, V, Hi);
|
|
|
|
|
|
|
|
// Emit X-Lo > Hi-Lo-1
|
|
|
|
Constant *AddCST = ConstantExpr::getNeg(Lo);
|
|
|
|
Instruction *Add = BinaryOperator::createAdd(V, AddCST, V->getName()+".off");
|
|
|
|
InsertNewInstBefore(Add, IB);
|
|
|
|
// Convert to unsigned for the comparison.
|
|
|
|
const Type *UnsType = Add->getType()->getUnsignedVersion();
|
|
|
|
Value *OffsetVal = InsertCastBefore(Add, UnsType, IB);
|
|
|
|
AddCST = ConstantExpr::getAdd(AddCST, Hi);
|
|
|
|
AddCST = ConstantExpr::getCast(AddCST, UnsType);
|
|
|
|
return new SetCondInst(Instruction::SetGT, OffsetVal, AddCST);
|
|
|
|
}
|
|
|
|
|
Refactor this code a bit and make it more general. This now compiles:
struct S { unsigned int i : 6, j : 11, k : 15; } b;
void plus2 (unsigned int x) { b.j += x; }
To:
_plus2:
lis r2, ha16(L_b$non_lazy_ptr)
lwz r2, lo16(L_b$non_lazy_ptr)(r2)
lwz r4, 0(r2)
slwi r3, r3, 6
add r3, r4, r3
rlwimi r3, r4, 0, 26, 14
stw r3, 0(r2)
blr
instead of:
_plus2:
lis r2, ha16(L_b$non_lazy_ptr)
lwz r2, lo16(L_b$non_lazy_ptr)(r2)
lwz r4, 0(r2)
rlwinm r5, r4, 26, 21, 31
add r3, r5, r3
rlwimi r4, r3, 6, 15, 25
stw r4, 0(r2)
blr
by eliminating an 'and'.
I'm pretty sure this is as small as we can go :)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23386 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-18 07:22:02 +00:00
|
|
|
// isRunOfOnes - Returns true iff Val consists of one contiguous run of 1s with
|
|
|
|
// any number of 0s on either side. The 1s are allowed to wrap from LSB to
|
|
|
|
// MSB, so 0x000FFF0, 0x0000FFFF, and 0xFF0000FF are all runs. 0x0F0F0000 is
|
|
|
|
// not, since all 1s are not contiguous.
|
|
|
|
static bool isRunOfOnes(ConstantIntegral *Val, unsigned &MB, unsigned &ME) {
|
|
|
|
uint64_t V = Val->getRawValue();
|
|
|
|
if (!isShiftedMask_64(V)) return false;
|
|
|
|
|
|
|
|
// look for the first zero bit after the run of ones
|
|
|
|
MB = 64-CountLeadingZeros_64((V - 1) ^ V);
|
|
|
|
// look for the first non-zero bit
|
|
|
|
ME = 64-CountLeadingZeros_64(V);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// FoldLogicalPlusAnd - This is part of an expression (LHS +/- RHS) & Mask,
|
|
|
|
/// where isSub determines whether the operator is a sub. If we can fold one of
|
|
|
|
/// the following xforms:
|
Implement add.ll:test29. Codegening:
struct S { unsigned int i : 6, j : 11, k : 15; } b;
void plus1 (unsigned int x) {
b.i += x;
}
as:
_plus1:
lis r2, ha16(L_b$non_lazy_ptr)
lwz r2, lo16(L_b$non_lazy_ptr)(r2)
lwz r4, 0(r2)
add r3, r4, r3
rlwimi r3, r4, 0, 0, 25
stw r3, 0(r2)
blr
instead of:
_plus1:
lis r2, ha16(L_b$non_lazy_ptr)
lwz r2, lo16(L_b$non_lazy_ptr)(r2)
lwz r4, 0(r2)
rlwinm r5, r4, 0, 26, 31
add r3, r5, r3
rlwimi r3, r4, 0, 0, 25
stw r3, 0(r2)
blr
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23379 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-18 04:24:45 +00:00
|
|
|
///
|
|
|
|
/// ((A & N) +/- B) & Mask -> (A +/- B) & Mask iff N&Mask == Mask
|
|
|
|
/// ((A | N) +/- B) & Mask -> (A +/- B) & Mask iff N&Mask == 0
|
|
|
|
/// ((A ^ N) +/- B) & Mask -> (A +/- B) & Mask iff N&Mask == 0
|
|
|
|
///
|
|
|
|
/// return (A +/- B).
|
|
|
|
///
|
|
|
|
Value *InstCombiner::FoldLogicalPlusAnd(Value *LHS, Value *RHS,
|
|
|
|
ConstantIntegral *Mask, bool isSub,
|
|
|
|
Instruction &I) {
|
|
|
|
Instruction *LHSI = dyn_cast<Instruction>(LHS);
|
|
|
|
if (!LHSI || LHSI->getNumOperands() != 2 ||
|
|
|
|
!isa<ConstantInt>(LHSI->getOperand(1))) return 0;
|
|
|
|
|
|
|
|
ConstantInt *N = cast<ConstantInt>(LHSI->getOperand(1));
|
|
|
|
|
|
|
|
switch (LHSI->getOpcode()) {
|
|
|
|
default: return 0;
|
|
|
|
case Instruction::And:
|
Refactor this code a bit and make it more general. This now compiles:
struct S { unsigned int i : 6, j : 11, k : 15; } b;
void plus2 (unsigned int x) { b.j += x; }
To:
_plus2:
lis r2, ha16(L_b$non_lazy_ptr)
lwz r2, lo16(L_b$non_lazy_ptr)(r2)
lwz r4, 0(r2)
slwi r3, r3, 6
add r3, r4, r3
rlwimi r3, r4, 0, 26, 14
stw r3, 0(r2)
blr
instead of:
_plus2:
lis r2, ha16(L_b$non_lazy_ptr)
lwz r2, lo16(L_b$non_lazy_ptr)(r2)
lwz r4, 0(r2)
rlwinm r5, r4, 26, 21, 31
add r3, r5, r3
rlwimi r4, r3, 6, 15, 25
stw r4, 0(r2)
blr
by eliminating an 'and'.
I'm pretty sure this is as small as we can go :)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23386 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-18 07:22:02 +00:00
|
|
|
if (ConstantExpr::getAnd(N, Mask) == Mask) {
|
|
|
|
// If the AndRHS is a power of two minus one (0+1+), this is simple.
|
|
|
|
if ((Mask->getRawValue() & Mask->getRawValue()+1) == 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
// Otherwise, if Mask is 0+1+0+, and if B is known to have the low 0+
|
|
|
|
// part, we don't need any explicit masks to take them out of A. If that
|
|
|
|
// is all N is, ignore it.
|
|
|
|
unsigned MB, ME;
|
|
|
|
if (isRunOfOnes(Mask, MB, ME)) { // begin/end bit of run, inclusive
|
2006-02-07 07:27:52 +00:00
|
|
|
uint64_t Mask = RHS->getType()->getIntegralTypeMask();
|
|
|
|
Mask >>= 64-MB+1;
|
|
|
|
if (MaskedValueIsZero(RHS, Mask))
|
Refactor this code a bit and make it more general. This now compiles:
struct S { unsigned int i : 6, j : 11, k : 15; } b;
void plus2 (unsigned int x) { b.j += x; }
To:
_plus2:
lis r2, ha16(L_b$non_lazy_ptr)
lwz r2, lo16(L_b$non_lazy_ptr)(r2)
lwz r4, 0(r2)
slwi r3, r3, 6
add r3, r4, r3
rlwimi r3, r4, 0, 26, 14
stw r3, 0(r2)
blr
instead of:
_plus2:
lis r2, ha16(L_b$non_lazy_ptr)
lwz r2, lo16(L_b$non_lazy_ptr)(r2)
lwz r4, 0(r2)
rlwinm r5, r4, 26, 21, 31
add r3, r5, r3
rlwimi r4, r3, 6, 15, 25
stw r4, 0(r2)
blr
by eliminating an 'and'.
I'm pretty sure this is as small as we can go :)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23386 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-18 07:22:02 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
Implement add.ll:test29. Codegening:
struct S { unsigned int i : 6, j : 11, k : 15; } b;
void plus1 (unsigned int x) {
b.i += x;
}
as:
_plus1:
lis r2, ha16(L_b$non_lazy_ptr)
lwz r2, lo16(L_b$non_lazy_ptr)(r2)
lwz r4, 0(r2)
add r3, r4, r3
rlwimi r3, r4, 0, 0, 25
stw r3, 0(r2)
blr
instead of:
_plus1:
lis r2, ha16(L_b$non_lazy_ptr)
lwz r2, lo16(L_b$non_lazy_ptr)(r2)
lwz r4, 0(r2)
rlwinm r5, r4, 0, 26, 31
add r3, r5, r3
rlwimi r3, r4, 0, 0, 25
stw r3, 0(r2)
blr
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23379 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-18 04:24:45 +00:00
|
|
|
return 0;
|
|
|
|
case Instruction::Or:
|
|
|
|
case Instruction::Xor:
|
Refactor this code a bit and make it more general. This now compiles:
struct S { unsigned int i : 6, j : 11, k : 15; } b;
void plus2 (unsigned int x) { b.j += x; }
To:
_plus2:
lis r2, ha16(L_b$non_lazy_ptr)
lwz r2, lo16(L_b$non_lazy_ptr)(r2)
lwz r4, 0(r2)
slwi r3, r3, 6
add r3, r4, r3
rlwimi r3, r4, 0, 26, 14
stw r3, 0(r2)
blr
instead of:
_plus2:
lis r2, ha16(L_b$non_lazy_ptr)
lwz r2, lo16(L_b$non_lazy_ptr)(r2)
lwz r4, 0(r2)
rlwinm r5, r4, 26, 21, 31
add r3, r5, r3
rlwimi r4, r3, 6, 15, 25
stw r4, 0(r2)
blr
by eliminating an 'and'.
I'm pretty sure this is as small as we can go :)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23386 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-18 07:22:02 +00:00
|
|
|
// If the AndRHS is a power of two minus one (0+1+), and N&Mask == 0
|
|
|
|
if ((Mask->getRawValue() & Mask->getRawValue()+1) == 0 &&
|
|
|
|
ConstantExpr::getAnd(N, Mask)->isNullValue())
|
Implement add.ll:test29. Codegening:
struct S { unsigned int i : 6, j : 11, k : 15; } b;
void plus1 (unsigned int x) {
b.i += x;
}
as:
_plus1:
lis r2, ha16(L_b$non_lazy_ptr)
lwz r2, lo16(L_b$non_lazy_ptr)(r2)
lwz r4, 0(r2)
add r3, r4, r3
rlwimi r3, r4, 0, 0, 25
stw r3, 0(r2)
blr
instead of:
_plus1:
lis r2, ha16(L_b$non_lazy_ptr)
lwz r2, lo16(L_b$non_lazy_ptr)(r2)
lwz r4, 0(r2)
rlwinm r5, r4, 0, 26, 31
add r3, r5, r3
rlwimi r3, r4, 0, 0, 25
stw r3, 0(r2)
blr
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23379 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-18 04:24:45 +00:00
|
|
|
break;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
Instruction *New;
|
|
|
|
if (isSub)
|
|
|
|
New = BinaryOperator::createSub(LHSI->getOperand(0), RHS, "fold");
|
|
|
|
else
|
|
|
|
New = BinaryOperator::createAdd(LHSI->getOperand(0), RHS, "fold");
|
|
|
|
return InsertNewInstBefore(New, I);
|
|
|
|
}
|
|
|
|
|
2002-06-25 16:13:24 +00:00
|
|
|
Instruction *InstCombiner::visitAnd(BinaryOperator &I) {
|
2003-03-10 21:43:22 +00:00
|
|
|
bool Changed = SimplifyCommutative(I);
|
2002-06-25 16:13:24 +00:00
|
|
|
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
2002-05-06 16:14:14 +00:00
|
|
|
|
2004-10-16 18:11:37 +00:00
|
|
|
if (isa<UndefValue>(Op1)) // X & undef -> 0
|
|
|
|
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
|
|
|
|
|
2005-01-01 16:22:27 +00:00
|
|
|
// and X, X = X
|
|
|
|
if (Op0 == Op1)
|
2002-08-12 21:17:25 +00:00
|
|
|
return ReplaceInstUsesWith(I, Op1);
|
2002-05-06 16:14:14 +00:00
|
|
|
|
2006-02-12 08:02:11 +00:00
|
|
|
// See if we can simplify any instructions used by the instruction whose sole
|
Use EraseInstFromFunction in a few cases to put the uses of the removed
instruction onto the worklist (in case they are now dead).
Add a really trivial local DSE implementation to help out bitfield code.
We now fold this:
struct S {
unsigned char a : 1, b : 1, c : 1, d : 2, e : 3;
S();
};
S::S() : a(0), b(0), c(1), d(0), e(6) {}
to this:
void %_ZN1SC1Ev(%struct.S* %this) {
entry:
%tmp.1 = getelementptr %struct.S* %this, int 0, uint 0
store ubyte 38, ubyte* %tmp.1
ret void
}
much earlier (in gccas instead of only in gccld after DSE runs).
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@26050 91177308-0d34-0410-b5e6-96231b3b80d8
2006-02-08 03:25:32 +00:00
|
|
|
// purpose is to compute bits we don't care about.
|
2006-02-11 09:31:47 +00:00
|
|
|
uint64_t KnownZero, KnownOne;
|
2006-03-25 21:58:26 +00:00
|
|
|
if (!isa<PackedType>(I.getType()) &&
|
|
|
|
SimplifyDemandedBits(&I, I.getType()->getIntegralTypeMask(),
|
2006-02-11 09:31:47 +00:00
|
|
|
KnownZero, KnownOne))
|
Use EraseInstFromFunction in a few cases to put the uses of the removed
instruction onto the worklist (in case they are now dead).
Add a really trivial local DSE implementation to help out bitfield code.
We now fold this:
struct S {
unsigned char a : 1, b : 1, c : 1, d : 2, e : 3;
S();
};
S::S() : a(0), b(0), c(1), d(0), e(6) {}
to this:
void %_ZN1SC1Ev(%struct.S* %this) {
entry:
%tmp.1 = getelementptr %struct.S* %this, int 0, uint 0
store ubyte 38, ubyte* %tmp.1
ret void
}
much earlier (in gccas instead of only in gccld after DSE runs).
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@26050 91177308-0d34-0410-b5e6-96231b3b80d8
2006-02-08 03:25:32 +00:00
|
|
|
return &I;
|
|
|
|
|
2005-01-01 16:22:27 +00:00
|
|
|
if (ConstantIntegral *AndRHS = dyn_cast<ConstantIntegral>(Op1)) {
|
2006-02-08 07:34:50 +00:00
|
|
|
uint64_t AndRHSMask = AndRHS->getZExtValue();
|
|
|
|
uint64_t TypeMask = Op0->getType()->getIntegralTypeMask();
|
|
|
|
uint64_t NotAndRHS = AndRHSMask^TypeMask;
|
2005-01-01 16:22:27 +00:00
|
|
|
|
2003-09-19 17:17:26 +00:00
|
|
|
// Optimize a variety of ((val OP C1) & C2) combinations...
|
|
|
|
if (isa<BinaryOperator>(Op0) || isa<ShiftInst>(Op0)) {
|
|
|
|
Instruction *Op0I = cast<Instruction>(Op0);
|
2005-01-01 16:22:27 +00:00
|
|
|
Value *Op0LHS = Op0I->getOperand(0);
|
|
|
|
Value *Op0RHS = Op0I->getOperand(1);
|
|
|
|
switch (Op0I->getOpcode()) {
|
|
|
|
case Instruction::Xor:
|
|
|
|
case Instruction::Or:
|
2005-01-23 20:26:55 +00:00
|
|
|
// If the mask is only needed on one incoming arm, push it up.
|
|
|
|
if (Op0I->hasOneUse()) {
|
|
|
|
if (MaskedValueIsZero(Op0LHS, NotAndRHS)) {
|
|
|
|
// Not masking anything out for the LHS, move to RHS.
|
|
|
|
Instruction *NewRHS = BinaryOperator::createAnd(Op0RHS, AndRHS,
|
|
|
|
Op0RHS->getName()+".masked");
|
|
|
|
InsertNewInstBefore(NewRHS, I);
|
|
|
|
return BinaryOperator::create(
|
|
|
|
cast<BinaryOperator>(Op0I)->getOpcode(), Op0LHS, NewRHS);
|
2005-04-21 23:48:37 +00:00
|
|
|
}
|
2006-02-07 07:27:52 +00:00
|
|
|
if (!isa<Constant>(Op0RHS) &&
|
2005-01-23 20:26:55 +00:00
|
|
|
MaskedValueIsZero(Op0RHS, NotAndRHS)) {
|
|
|
|
// Not masking anything out for the RHS, move to LHS.
|
|
|
|
Instruction *NewLHS = BinaryOperator::createAnd(Op0LHS, AndRHS,
|
|
|
|
Op0LHS->getName()+".masked");
|
|
|
|
InsertNewInstBefore(NewLHS, I);
|
|
|
|
return BinaryOperator::create(
|
|
|
|
cast<BinaryOperator>(Op0I)->getOpcode(), NewLHS, Op0RHS);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-01-01 16:22:27 +00:00
|
|
|
break;
|
Implement add.ll:test29. Codegening:
struct S { unsigned int i : 6, j : 11, k : 15; } b;
void plus1 (unsigned int x) {
b.i += x;
}
as:
_plus1:
lis r2, ha16(L_b$non_lazy_ptr)
lwz r2, lo16(L_b$non_lazy_ptr)(r2)
lwz r4, 0(r2)
add r3, r4, r3
rlwimi r3, r4, 0, 0, 25
stw r3, 0(r2)
blr
instead of:
_plus1:
lis r2, ha16(L_b$non_lazy_ptr)
lwz r2, lo16(L_b$non_lazy_ptr)(r2)
lwz r4, 0(r2)
rlwinm r5, r4, 0, 26, 31
add r3, r5, r3
rlwimi r3, r4, 0, 0, 25
stw r3, 0(r2)
blr
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23379 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-18 04:24:45 +00:00
|
|
|
case Instruction::Add:
|
Refactor this code a bit and make it more general. This now compiles:
struct S { unsigned int i : 6, j : 11, k : 15; } b;
void plus2 (unsigned int x) { b.j += x; }
To:
_plus2:
lis r2, ha16(L_b$non_lazy_ptr)
lwz r2, lo16(L_b$non_lazy_ptr)(r2)
lwz r4, 0(r2)
slwi r3, r3, 6
add r3, r4, r3
rlwimi r3, r4, 0, 26, 14
stw r3, 0(r2)
blr
instead of:
_plus2:
lis r2, ha16(L_b$non_lazy_ptr)
lwz r2, lo16(L_b$non_lazy_ptr)(r2)
lwz r4, 0(r2)
rlwinm r5, r4, 26, 21, 31
add r3, r5, r3
rlwimi r4, r3, 6, 15, 25
stw r4, 0(r2)
blr
by eliminating an 'and'.
I'm pretty sure this is as small as we can go :)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23386 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-18 07:22:02 +00:00
|
|
|
// ((A & N) + B) & AndRHS -> (A + B) & AndRHS iff N&AndRHS == AndRHS.
|
|
|
|
// ((A | N) + B) & AndRHS -> (A + B) & AndRHS iff N&AndRHS == 0
|
|
|
|
// ((A ^ N) + B) & AndRHS -> (A + B) & AndRHS iff N&AndRHS == 0
|
|
|
|
if (Value *V = FoldLogicalPlusAnd(Op0LHS, Op0RHS, AndRHS, false, I))
|
|
|
|
return BinaryOperator::createAnd(V, AndRHS);
|
|
|
|
if (Value *V = FoldLogicalPlusAnd(Op0RHS, Op0LHS, AndRHS, false, I))
|
|
|
|
return BinaryOperator::createAnd(V, AndRHS); // Add commutes
|
Implement add.ll:test29. Codegening:
struct S { unsigned int i : 6, j : 11, k : 15; } b;
void plus1 (unsigned int x) {
b.i += x;
}
as:
_plus1:
lis r2, ha16(L_b$non_lazy_ptr)
lwz r2, lo16(L_b$non_lazy_ptr)(r2)
lwz r4, 0(r2)
add r3, r4, r3
rlwimi r3, r4, 0, 0, 25
stw r3, 0(r2)
blr
instead of:
_plus1:
lis r2, ha16(L_b$non_lazy_ptr)
lwz r2, lo16(L_b$non_lazy_ptr)(r2)
lwz r4, 0(r2)
rlwinm r5, r4, 0, 26, 31
add r3, r5, r3
rlwimi r3, r4, 0, 0, 25
stw r3, 0(r2)
blr
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23379 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-18 04:24:45 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case Instruction::Sub:
|
Refactor this code a bit and make it more general. This now compiles:
struct S { unsigned int i : 6, j : 11, k : 15; } b;
void plus2 (unsigned int x) { b.j += x; }
To:
_plus2:
lis r2, ha16(L_b$non_lazy_ptr)
lwz r2, lo16(L_b$non_lazy_ptr)(r2)
lwz r4, 0(r2)
slwi r3, r3, 6
add r3, r4, r3
rlwimi r3, r4, 0, 26, 14
stw r3, 0(r2)
blr
instead of:
_plus2:
lis r2, ha16(L_b$non_lazy_ptr)
lwz r2, lo16(L_b$non_lazy_ptr)(r2)
lwz r4, 0(r2)
rlwinm r5, r4, 26, 21, 31
add r3, r5, r3
rlwimi r4, r3, 6, 15, 25
stw r4, 0(r2)
blr
by eliminating an 'and'.
I'm pretty sure this is as small as we can go :)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23386 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-18 07:22:02 +00:00
|
|
|
// ((A & N) - B) & AndRHS -> (A - B) & AndRHS iff N&AndRHS == AndRHS.
|
|
|
|
// ((A | N) - B) & AndRHS -> (A - B) & AndRHS iff N&AndRHS == 0
|
|
|
|
// ((A ^ N) - B) & AndRHS -> (A - B) & AndRHS iff N&AndRHS == 0
|
|
|
|
if (Value *V = FoldLogicalPlusAnd(Op0LHS, Op0RHS, AndRHS, true, I))
|
|
|
|
return BinaryOperator::createAnd(V, AndRHS);
|
Implement add.ll:test29. Codegening:
struct S { unsigned int i : 6, j : 11, k : 15; } b;
void plus1 (unsigned int x) {
b.i += x;
}
as:
_plus1:
lis r2, ha16(L_b$non_lazy_ptr)
lwz r2, lo16(L_b$non_lazy_ptr)(r2)
lwz r4, 0(r2)
add r3, r4, r3
rlwimi r3, r4, 0, 0, 25
stw r3, 0(r2)
blr
instead of:
_plus1:
lis r2, ha16(L_b$non_lazy_ptr)
lwz r2, lo16(L_b$non_lazy_ptr)(r2)
lwz r4, 0(r2)
rlwinm r5, r4, 0, 26, 31
add r3, r5, r3
rlwimi r3, r4, 0, 0, 25
stw r3, 0(r2)
blr
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23379 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-18 04:24:45 +00:00
|
|
|
break;
|
2005-01-01 16:22:27 +00:00
|
|
|
}
|
|
|
|
|
2003-07-23 19:25:52 +00:00
|
|
|
if (ConstantInt *Op0CI = dyn_cast<ConstantInt>(Op0I->getOperand(1)))
|
2005-01-01 16:22:27 +00:00
|
|
|
if (Instruction *Res = OptAndOp(Op0I, Op0CI, AndRHS, I))
|
2003-09-19 17:17:26 +00:00
|
|
|
return Res;
|
2005-01-01 16:22:27 +00:00
|
|
|
} else if (CastInst *CI = dyn_cast<CastInst>(Op0)) {
|
|
|
|
const Type *SrcTy = CI->getOperand(0)->getType();
|
|
|
|
|
2005-08-07 07:03:10 +00:00
|
|
|
// If this is an integer truncation or change from signed-to-unsigned, and
|
|
|
|
// if the source is an and/or with immediate, transform it. This
|
|
|
|
// frequently occurs for bitfield accesses.
|
|
|
|
if (Instruction *CastOp = dyn_cast<Instruction>(CI->getOperand(0))) {
|
|
|
|
if (SrcTy->getPrimitiveSizeInBits() >=
|
|
|
|
I.getType()->getPrimitiveSizeInBits() &&
|
|
|
|
CastOp->getNumOperands() == 2)
|
2006-02-08 07:34:50 +00:00
|
|
|
if (ConstantInt *AndCI = dyn_cast<ConstantInt>(CastOp->getOperand(1)))
|
2005-08-07 07:03:10 +00:00
|
|
|
if (CastOp->getOpcode() == Instruction::And) {
|
|
|
|
// Change: and (cast (and X, C1) to T), C2
|
|
|
|
// into : and (cast X to T), trunc(C1)&C2
|
|
|
|
// This will folds the two ands together, which may allow other
|
|
|
|
// simplifications.
|
|
|
|
Instruction *NewCast =
|
|
|
|
new CastInst(CastOp->getOperand(0), I.getType(),
|
|
|
|
CastOp->getName()+".shrunk");
|
|
|
|
NewCast = InsertNewInstBefore(NewCast, I);
|
|
|
|
|
|
|
|
Constant *C3=ConstantExpr::getCast(AndCI, I.getType());//trunc(C1)
|
|
|
|
C3 = ConstantExpr::getAnd(C3, AndRHS); // trunc(C1)&C2
|
|
|
|
return BinaryOperator::createAnd(NewCast, C3);
|
|
|
|
} else if (CastOp->getOpcode() == Instruction::Or) {
|
|
|
|
// Change: and (cast (or X, C1) to T), C2
|
|
|
|
// into : trunc(C1)&C2 iff trunc(C1)&C2 == C2
|
|
|
|
Constant *C3=ConstantExpr::getCast(AndCI, I.getType());//trunc(C1)
|
|
|
|
if (ConstantExpr::getAnd(C3, AndRHS) == AndRHS) // trunc(C1)&C2
|
|
|
|
return ReplaceInstUsesWith(I, AndRHS);
|
|
|
|
}
|
|
|
|
}
|
2003-07-23 19:36:21 +00:00
|
|
|
}
|
2004-04-09 19:05:30 +00:00
|
|
|
|
|
|
|
// Try to fold constant and into select arguments.
|
|
|
|
if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
|
2005-01-01 16:22:27 +00:00
|
|
|
if (Instruction *R = FoldOpIntoSelect(I, SI, this))
|
2004-04-09 19:05:30 +00:00
|
|
|
return R;
|
Fold binary expressions and casts into PHI nodes that have all constant inputs.
This takes something like this:
%A = phi int [ 3, %cond_false.0 ], [ 2, %endif.0.i ], [ 2, %endif.1.i ]
%B = div int %tmp.243, 4
and turns it into:
%A = phi int [ 3/4, %cond_false.0 ], [ 2/4, %endif.0.i ], [ 2/4, %endif.1.i ]
which is later simplified (in this case) into %A = 0.
This triggers thousands of times in spec, for example, 269 times in 176.gcc.
This is tested by InstCombine/add.ll:test23 and set.ll:test18.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16582 91177308-0d34-0410-b5e6-96231b3b80d8
2004-09-29 05:07:12 +00:00
|
|
|
if (isa<PHINode>(Op0))
|
|
|
|
if (Instruction *NV = FoldOpIntoPhi(I))
|
|
|
|
return NV;
|
2003-07-23 17:57:01 +00:00
|
|
|
}
|
|
|
|
|
2003-03-10 23:06:50 +00:00
|
|
|
Value *Op0NotVal = dyn_castNotVal(Op0);
|
|
|
|
Value *Op1NotVal = dyn_castNotVal(Op1);
|
2003-02-18 19:28:33 +00:00
|
|
|
|
2004-06-18 06:07:51 +00:00
|
|
|
if (Op0NotVal == Op1 || Op1NotVal == Op0) // A & ~A == ~A & A == 0
|
|
|
|
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
|
|
|
|
|
2004-07-30 12:50:08 +00:00
|
|
|
// (~A & ~B) == (~(A | B)) - De Morgan's Law
|
2003-03-10 23:06:50 +00:00
|
|
|
if (Op0NotVal && Op1NotVal && isOnlyUse(Op0) && isOnlyUse(Op1)) {
|
2004-06-10 02:07:29 +00:00
|
|
|
Instruction *Or = BinaryOperator::createOr(Op0NotVal, Op1NotVal,
|
|
|
|
I.getName()+".demorgan");
|
2003-07-23 17:57:01 +00:00
|
|
|
InsertNewInstBefore(Or, I);
|
2003-02-18 19:28:33 +00:00
|
|
|
return BinaryOperator::createNot(Or);
|
|
|
|
}
|
2006-02-13 23:07:23 +00:00
|
|
|
|
|
|
|
{
|
|
|
|
Value *A = 0, *B = 0;
|
|
|
|
ConstantInt *C1 = 0, *C2 = 0;
|
|
|
|
if (match(Op0, m_Or(m_Value(A), m_Value(B))))
|
|
|
|
if (A == Op1 || B == Op1) // (A | ?) & A --> A
|
|
|
|
return ReplaceInstUsesWith(I, Op1);
|
|
|
|
if (match(Op1, m_Or(m_Value(A), m_Value(B))))
|
|
|
|
if (A == Op0 || B == Op0) // A & (A | ?) --> A
|
|
|
|
return ReplaceInstUsesWith(I, Op0);
|
2006-04-01 08:03:55 +00:00
|
|
|
|
|
|
|
if (Op0->hasOneUse() &&
|
|
|
|
match(Op0, m_Xor(m_Value(A), m_Value(B)))) {
|
|
|
|
if (A == Op1) { // (A^B)&A -> A&(A^B)
|
|
|
|
I.swapOperands(); // Simplify below
|
|
|
|
std::swap(Op0, Op1);
|
|
|
|
} else if (B == Op1) { // (A^B)&B -> B&(B^A)
|
|
|
|
cast<BinaryOperator>(Op0)->swapOperands();
|
|
|
|
I.swapOperands(); // Simplify below
|
|
|
|
std::swap(Op0, Op1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (Op1->hasOneUse() &&
|
|
|
|
match(Op1, m_Xor(m_Value(A), m_Value(B)))) {
|
|
|
|
if (B == Op0) { // B&(A^B) -> B&(B^A)
|
|
|
|
cast<BinaryOperator>(Op1)->swapOperands();
|
|
|
|
std::swap(A, B);
|
|
|
|
}
|
|
|
|
if (A == Op0) { // A&(A^B) -> A & ~B
|
|
|
|
Instruction *NotB = BinaryOperator::createNot(B, "tmp");
|
|
|
|
InsertNewInstBefore(NotB, I);
|
|
|
|
return BinaryOperator::createAnd(A, NotB);
|
|
|
|
}
|
|
|
|
}
|
2006-02-13 23:07:23 +00:00
|
|
|
}
|
|
|
|
|
2003-02-18 19:28:33 +00:00
|
|
|
|
Fold (and (setcc X, C1), (setcc X, C2))
This is important for several reasons:
1. Benchmarks have lots of code that looks like this (perlbmk in particular):
%tmp.2.i = setne int %tmp.0.i, 128 ; <bool> [#uses=1]
%tmp.6343 = seteq int %tmp.0.i, 1 ; <bool> [#uses=1]
%tmp.63 = and bool %tmp.2.i, %tmp.6343 ; <bool> [#uses=1]
we now fold away the setne, a clear improvement.
2. In the more important cases, such as (X >= 10) & (X < 20), we now produce
smaller code: (X-10) < 10.
3. Perhaps the nicest effect of this patch is that it really helps out the
code generators. In particular, for a 'range test' like the above,
instead of generating this on X86 (the difference on PPC is even more
pronounced):
cmp %EAX, 50
setge %CL
cmp %EAX, 100
setl %AL
and %CL, %AL
cmp %CL, 0
we now generate this:
add %EAX, -50
cmp %EAX, 50
Furthermore, this causes setcc's to be folded into branches more often.
These combinations trigger dozens of times in the spec benchmarks, particularly
in 176.gcc, 186.crafty, 253.perlbmk, 254.gap, & 099.go.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16559 91177308-0d34-0410-b5e6-96231b3b80d8
2004-09-28 21:48:02 +00:00
|
|
|
if (SetCondInst *RHS = dyn_cast<SetCondInst>(Op1)) {
|
|
|
|
// (setcc1 A, B) & (setcc2 A, B) --> (setcc3 A, B)
|
2003-08-13 20:16:26 +00:00
|
|
|
if (Instruction *R = AssociativeOpt(I, FoldSetCCLogical(*this, RHS)))
|
|
|
|
return R;
|
|
|
|
|
Fold (and (setcc X, C1), (setcc X, C2))
This is important for several reasons:
1. Benchmarks have lots of code that looks like this (perlbmk in particular):
%tmp.2.i = setne int %tmp.0.i, 128 ; <bool> [#uses=1]
%tmp.6343 = seteq int %tmp.0.i, 1 ; <bool> [#uses=1]
%tmp.63 = and bool %tmp.2.i, %tmp.6343 ; <bool> [#uses=1]
we now fold away the setne, a clear improvement.
2. In the more important cases, such as (X >= 10) & (X < 20), we now produce
smaller code: (X-10) < 10.
3. Perhaps the nicest effect of this patch is that it really helps out the
code generators. In particular, for a 'range test' like the above,
instead of generating this on X86 (the difference on PPC is even more
pronounced):
cmp %EAX, 50
setge %CL
cmp %EAX, 100
setl %AL
and %CL, %AL
cmp %CL, 0
we now generate this:
add %EAX, -50
cmp %EAX, 50
Furthermore, this causes setcc's to be folded into branches more often.
These combinations trigger dozens of times in the spec benchmarks, particularly
in 176.gcc, 186.crafty, 253.perlbmk, 254.gap, & 099.go.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16559 91177308-0d34-0410-b5e6-96231b3b80d8
2004-09-28 21:48:02 +00:00
|
|
|
Value *LHSVal, *RHSVal;
|
|
|
|
ConstantInt *LHSCst, *RHSCst;
|
|
|
|
Instruction::BinaryOps LHSCC, RHSCC;
|
|
|
|
if (match(Op0, m_SetCond(LHSCC, m_Value(LHSVal), m_ConstantInt(LHSCst))))
|
|
|
|
if (match(RHS, m_SetCond(RHSCC, m_Value(RHSVal), m_ConstantInt(RHSCst))))
|
|
|
|
if (LHSVal == RHSVal && // Found (X setcc C1) & (X setcc C2)
|
|
|
|
// Set[GL]E X, CST is folded to Set[GL]T elsewhere.
|
2005-04-21 23:48:37 +00:00
|
|
|
LHSCC != Instruction::SetGE && LHSCC != Instruction::SetLE &&
|
Fold (and (setcc X, C1), (setcc X, C2))
This is important for several reasons:
1. Benchmarks have lots of code that looks like this (perlbmk in particular):
%tmp.2.i = setne int %tmp.0.i, 128 ; <bool> [#uses=1]
%tmp.6343 = seteq int %tmp.0.i, 1 ; <bool> [#uses=1]
%tmp.63 = and bool %tmp.2.i, %tmp.6343 ; <bool> [#uses=1]
we now fold away the setne, a clear improvement.
2. In the more important cases, such as (X >= 10) & (X < 20), we now produce
smaller code: (X-10) < 10.
3. Perhaps the nicest effect of this patch is that it really helps out the
code generators. In particular, for a 'range test' like the above,
instead of generating this on X86 (the difference on PPC is even more
pronounced):
cmp %EAX, 50
setge %CL
cmp %EAX, 100
setl %AL
and %CL, %AL
cmp %CL, 0
we now generate this:
add %EAX, -50
cmp %EAX, 50
Furthermore, this causes setcc's to be folded into branches more often.
These combinations trigger dozens of times in the spec benchmarks, particularly
in 176.gcc, 186.crafty, 253.perlbmk, 254.gap, & 099.go.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16559 91177308-0d34-0410-b5e6-96231b3b80d8
2004-09-28 21:48:02 +00:00
|
|
|
RHSCC != Instruction::SetGE && RHSCC != Instruction::SetLE) {
|
|
|
|
// Ensure that the larger constant is on the RHS.
|
|
|
|
Constant *Cmp = ConstantExpr::getSetGT(LHSCst, RHSCst);
|
|
|
|
SetCondInst *LHS = cast<SetCondInst>(Op0);
|
|
|
|
if (cast<ConstantBool>(Cmp)->getValue()) {
|
|
|
|
std::swap(LHS, RHS);
|
|
|
|
std::swap(LHSCst, RHSCst);
|
|
|
|
std::swap(LHSCC, RHSCC);
|
|
|
|
}
|
|
|
|
|
|
|
|
// At this point, we know we have have two setcc instructions
|
|
|
|
// comparing a value against two constants and and'ing the result
|
|
|
|
// together. Because of the above check, we know that we only have
|
|
|
|
// SetEQ, SetNE, SetLT, and SetGT here. We also know (from the
|
|
|
|
// FoldSetCCLogical check above), that the two constants are not
|
|
|
|
// equal.
|
|
|
|
assert(LHSCst != RHSCst && "Compares not folded above?");
|
|
|
|
|
|
|
|
switch (LHSCC) {
|
|
|
|
default: assert(0 && "Unknown integer condition code!");
|
|
|
|
case Instruction::SetEQ:
|
|
|
|
switch (RHSCC) {
|
|
|
|
default: assert(0 && "Unknown integer condition code!");
|
|
|
|
case Instruction::SetEQ: // (X == 13 & X == 15) -> false
|
|
|
|
case Instruction::SetGT: // (X == 13 & X > 15) -> false
|
|
|
|
return ReplaceInstUsesWith(I, ConstantBool::False);
|
|
|
|
case Instruction::SetNE: // (X == 13 & X != 15) -> X == 13
|
|
|
|
case Instruction::SetLT: // (X == 13 & X < 15) -> X == 13
|
|
|
|
return ReplaceInstUsesWith(I, LHS);
|
|
|
|
}
|
|
|
|
case Instruction::SetNE:
|
|
|
|
switch (RHSCC) {
|
|
|
|
default: assert(0 && "Unknown integer condition code!");
|
|
|
|
case Instruction::SetLT:
|
|
|
|
if (LHSCst == SubOne(RHSCst)) // (X != 13 & X < 14) -> X < 13
|
|
|
|
return new SetCondInst(Instruction::SetLT, LHSVal, LHSCst);
|
|
|
|
break; // (X != 13 & X < 15) -> no change
|
|
|
|
case Instruction::SetEQ: // (X != 13 & X == 15) -> X == 15
|
|
|
|
case Instruction::SetGT: // (X != 13 & X > 15) -> X > 15
|
|
|
|
return ReplaceInstUsesWith(I, RHS);
|
|
|
|
case Instruction::SetNE:
|
|
|
|
if (LHSCst == SubOne(RHSCst)) {// (X != 13 & X != 14) -> X-13 >u 1
|
|
|
|
Constant *AddCST = ConstantExpr::getNeg(LHSCst);
|
|
|
|
Instruction *Add = BinaryOperator::createAdd(LHSVal, AddCST,
|
|
|
|
LHSVal->getName()+".off");
|
|
|
|
InsertNewInstBefore(Add, I);
|
|
|
|
const Type *UnsType = Add->getType()->getUnsignedVersion();
|
|
|
|
Value *OffsetVal = InsertCastBefore(Add, UnsType, I);
|
|
|
|
AddCST = ConstantExpr::getSub(RHSCst, LHSCst);
|
|
|
|
AddCST = ConstantExpr::getCast(AddCST, UnsType);
|
|
|
|
return new SetCondInst(Instruction::SetGT, OffsetVal, AddCST);
|
|
|
|
}
|
|
|
|
break; // (X != 13 & X != 15) -> no change
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case Instruction::SetLT:
|
|
|
|
switch (RHSCC) {
|
|
|
|
default: assert(0 && "Unknown integer condition code!");
|
|
|
|
case Instruction::SetEQ: // (X < 13 & X == 15) -> false
|
|
|
|
case Instruction::SetGT: // (X < 13 & X > 15) -> false
|
|
|
|
return ReplaceInstUsesWith(I, ConstantBool::False);
|
|
|
|
case Instruction::SetNE: // (X < 13 & X != 15) -> X < 13
|
|
|
|
case Instruction::SetLT: // (X < 13 & X < 15) -> X < 13
|
|
|
|
return ReplaceInstUsesWith(I, LHS);
|
|
|
|
}
|
|
|
|
case Instruction::SetGT:
|
|
|
|
switch (RHSCC) {
|
|
|
|
default: assert(0 && "Unknown integer condition code!");
|
|
|
|
case Instruction::SetEQ: // (X > 13 & X == 15) -> X > 13
|
|
|
|
return ReplaceInstUsesWith(I, LHS);
|
|
|
|
case Instruction::SetGT: // (X > 13 & X > 15) -> X > 15
|
|
|
|
return ReplaceInstUsesWith(I, RHS);
|
|
|
|
case Instruction::SetNE:
|
|
|
|
if (RHSCst == AddOne(LHSCst)) // (X > 13 & X != 14) -> X > 14
|
|
|
|
return new SetCondInst(Instruction::SetGT, LHSVal, RHSCst);
|
|
|
|
break; // (X > 13 & X != 15) -> no change
|
2004-09-29 17:40:11 +00:00
|
|
|
case Instruction::SetLT: // (X > 13 & X < 15) -> (X-14) <u 1
|
|
|
|
return InsertRangeTest(LHSVal, AddOne(LHSCst), RHSCst, true, I);
|
Fold (and (setcc X, C1), (setcc X, C2))
This is important for several reasons:
1. Benchmarks have lots of code that looks like this (perlbmk in particular):
%tmp.2.i = setne int %tmp.0.i, 128 ; <bool> [#uses=1]
%tmp.6343 = seteq int %tmp.0.i, 1 ; <bool> [#uses=1]
%tmp.63 = and bool %tmp.2.i, %tmp.6343 ; <bool> [#uses=1]
we now fold away the setne, a clear improvement.
2. In the more important cases, such as (X >= 10) & (X < 20), we now produce
smaller code: (X-10) < 10.
3. Perhaps the nicest effect of this patch is that it really helps out the
code generators. In particular, for a 'range test' like the above,
instead of generating this on X86 (the difference on PPC is even more
pronounced):
cmp %EAX, 50
setge %CL
cmp %EAX, 100
setl %AL
and %CL, %AL
cmp %CL, 0
we now generate this:
add %EAX, -50
cmp %EAX, 50
Furthermore, this causes setcc's to be folded into branches more often.
These combinations trigger dozens of times in the spec benchmarks, particularly
in 176.gcc, 186.crafty, 253.perlbmk, 254.gap, & 099.go.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16559 91177308-0d34-0410-b5e6-96231b3b80d8
2004-09-28 21:48:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-05-05 06:39:07 +00:00
|
|
|
// fold (and (cast A), (cast B)) -> (cast (and A, B))
|
|
|
|
if (CastInst *Op0C = dyn_cast<CastInst>(Op0)) {
|
2006-05-05 20:51:30 +00:00
|
|
|
const Type *SrcTy = Op0C->getOperand(0)->getType();
|
2006-05-05 06:39:07 +00:00
|
|
|
if (CastInst *Op1C = dyn_cast<CastInst>(Op1))
|
2006-05-05 20:51:30 +00:00
|
|
|
if (SrcTy == Op1C->getOperand(0)->getType() && SrcTy->isIntegral() &&
|
2006-05-06 09:00:16 +00:00
|
|
|
// Only do this if the casts both really cause code to be generated.
|
|
|
|
ValueRequiresCast(Op0C->getOperand(0), I.getType(), TD) &&
|
|
|
|
ValueRequiresCast(Op1C->getOperand(0), I.getType(), TD)) {
|
2006-05-05 06:39:07 +00:00
|
|
|
Instruction *NewOp = BinaryOperator::createAnd(Op0C->getOperand(0),
|
|
|
|
Op1C->getOperand(0),
|
|
|
|
I.getName());
|
|
|
|
InsertNewInstBefore(NewOp, I);
|
|
|
|
return new CastInst(NewOp, I.getType());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-06-25 16:13:24 +00:00
|
|
|
return Changed ? &I : 0;
|
2002-05-06 16:14:14 +00:00
|
|
|
}
|
|
|
|
|
2002-06-25 16:13:24 +00:00
|
|
|
Instruction *InstCombiner::visitOr(BinaryOperator &I) {
|
2003-03-10 21:43:22 +00:00
|
|
|
bool Changed = SimplifyCommutative(I);
|
2002-06-25 16:13:24 +00:00
|
|
|
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
2002-05-06 16:14:14 +00:00
|
|
|
|
2004-10-16 18:11:37 +00:00
|
|
|
if (isa<UndefValue>(Op1))
|
|
|
|
return ReplaceInstUsesWith(I, // X | undef -> -1
|
|
|
|
ConstantIntegral::getAllOnesValue(I.getType()));
|
|
|
|
|
2006-02-12 08:02:11 +00:00
|
|
|
// or X, X = X
|
|
|
|
if (Op0 == Op1)
|
2002-08-12 21:17:25 +00:00
|
|
|
return ReplaceInstUsesWith(I, Op0);
|
2002-05-06 16:14:14 +00:00
|
|
|
|
2006-02-12 08:02:11 +00:00
|
|
|
// See if we can simplify any instructions used by the instruction whose sole
|
|
|
|
// purpose is to compute bits we don't care about.
|
|
|
|
uint64_t KnownZero, KnownOne;
|
2006-03-25 21:58:26 +00:00
|
|
|
if (!isa<PackedType>(I.getType()) &&
|
|
|
|
SimplifyDemandedBits(&I, I.getType()->getIntegralTypeMask(),
|
2006-02-12 08:02:11 +00:00
|
|
|
KnownZero, KnownOne))
|
|
|
|
return &I;
|
|
|
|
|
2002-05-06 16:14:14 +00:00
|
|
|
// or X, -1 == -1
|
2003-07-23 18:29:44 +00:00
|
|
|
if (ConstantIntegral *RHS = dyn_cast<ConstantIntegral>(Op1)) {
|
2006-01-06 17:59:59 +00:00
|
|
|
ConstantInt *C1 = 0; Value *X = 0;
|
2004-07-30 07:50:03 +00:00
|
|
|
// (X & C1) | C2 --> (X | C2) & (C1|C2)
|
|
|
|
if (match(Op0, m_And(m_Value(X), m_ConstantInt(C1))) && isOnlyUse(Op0)) {
|
2005-05-09 04:58:36 +00:00
|
|
|
Instruction *Or = BinaryOperator::createOr(X, RHS, Op0->getName());
|
|
|
|
Op0->setName("");
|
2004-07-30 07:50:03 +00:00
|
|
|
InsertNewInstBefore(Or, I);
|
|
|
|
return BinaryOperator::createAnd(Or, ConstantExpr::getOr(RHS, C1));
|
|
|
|
}
|
2003-07-23 18:29:44 +00:00
|
|
|
|
2004-07-30 07:50:03 +00:00
|
|
|
// (X ^ C1) | C2 --> (X | C2) ^ (C1&~C2)
|
|
|
|
if (match(Op0, m_Xor(m_Value(X), m_ConstantInt(C1))) && isOnlyUse(Op0)) {
|
|
|
|
std::string Op0Name = Op0->getName(); Op0->setName("");
|
|
|
|
Instruction *Or = BinaryOperator::createOr(X, RHS, Op0Name);
|
|
|
|
InsertNewInstBefore(Or, I);
|
|
|
|
return BinaryOperator::createXor(Or,
|
|
|
|
ConstantExpr::getAnd(C1, ConstantExpr::getNot(RHS)));
|
2003-07-23 18:29:44 +00:00
|
|
|
}
|
2004-04-09 19:05:30 +00:00
|
|
|
|
|
|
|
// Try to fold constant and into select arguments.
|
|
|
|
if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
|
2005-01-01 16:22:27 +00:00
|
|
|
if (Instruction *R = FoldOpIntoSelect(I, SI, this))
|
2004-04-09 19:05:30 +00:00
|
|
|
return R;
|
Fold binary expressions and casts into PHI nodes that have all constant inputs.
This takes something like this:
%A = phi int [ 3, %cond_false.0 ], [ 2, %endif.0.i ], [ 2, %endif.1.i ]
%B = div int %tmp.243, 4
and turns it into:
%A = phi int [ 3/4, %cond_false.0 ], [ 2/4, %endif.0.i ], [ 2/4, %endif.1.i ]
which is later simplified (in this case) into %A = 0.
This triggers thousands of times in spec, for example, 269 times in 176.gcc.
This is tested by InstCombine/add.ll:test23 and set.ll:test18.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16582 91177308-0d34-0410-b5e6-96231b3b80d8
2004-09-29 05:07:12 +00:00
|
|
|
if (isa<PHINode>(Op0))
|
|
|
|
if (Instruction *NV = FoldOpIntoPhi(I))
|
|
|
|
return NV;
|
2003-07-23 18:29:44 +00:00
|
|
|
}
|
|
|
|
|
2006-01-06 17:59:59 +00:00
|
|
|
Value *A = 0, *B = 0;
|
|
|
|
ConstantInt *C1 = 0, *C2 = 0;
|
2005-05-07 23:49:08 +00:00
|
|
|
|
|
|
|
if (match(Op0, m_And(m_Value(A), m_Value(B))))
|
|
|
|
if (A == Op1 || B == Op1) // (A & ?) | A --> A
|
|
|
|
return ReplaceInstUsesWith(I, Op1);
|
|
|
|
if (match(Op1, m_And(m_Value(A), m_Value(B))))
|
|
|
|
if (A == Op0 || B == Op0) // A | (A & ?) --> A
|
|
|
|
return ReplaceInstUsesWith(I, Op0);
|
|
|
|
|
2005-05-09 04:58:36 +00:00
|
|
|
// (X^C)|Y -> (X|Y)^C iff Y&C == 0
|
|
|
|
if (Op0->hasOneUse() && match(Op0, m_Xor(m_Value(A), m_ConstantInt(C1))) &&
|
2006-02-07 07:27:52 +00:00
|
|
|
MaskedValueIsZero(Op1, C1->getZExtValue())) {
|
2005-05-09 04:58:36 +00:00
|
|
|
Instruction *NOr = BinaryOperator::createOr(A, Op1, Op0->getName());
|
|
|
|
Op0->setName("");
|
|
|
|
return BinaryOperator::createXor(InsertNewInstBefore(NOr, I), C1);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Y|(X^C) -> (X|Y)^C iff Y&C == 0
|
|
|
|
if (Op1->hasOneUse() && match(Op1, m_Xor(m_Value(A), m_ConstantInt(C1))) &&
|
2006-02-07 07:27:52 +00:00
|
|
|
MaskedValueIsZero(Op0, C1->getZExtValue())) {
|
2005-05-09 04:58:36 +00:00
|
|
|
Instruction *NOr = BinaryOperator::createOr(A, Op0, Op1->getName());
|
|
|
|
Op0->setName("");
|
|
|
|
return BinaryOperator::createXor(InsertNewInstBefore(NOr, I), C1);
|
|
|
|
}
|
|
|
|
|
2005-09-18 03:42:07 +00:00
|
|
|
// (A & C1)|(B & C2)
|
2004-07-30 07:50:03 +00:00
|
|
|
if (match(Op0, m_And(m_Value(A), m_ConstantInt(C1))) &&
|
2005-09-18 03:42:07 +00:00
|
|
|
match(Op1, m_And(m_Value(B), m_ConstantInt(C2)))) {
|
|
|
|
|
|
|
|
if (A == B) // (A & C1)|(A & C2) == A & (C1|C2)
|
|
|
|
return BinaryOperator::createAnd(A, ConstantExpr::getOr(C1, C2));
|
|
|
|
|
|
|
|
|
Generalize this transform, using MaskedValueIsZero, allowing us to compile:
struct S { unsigned int i : 6, j : 11, k : 15; } b;
void plus3 (unsigned int x) { b.k += x; }
To:
plus3:
mov %EAX, DWORD PTR [%ESP + 4]
shl %EAX, 17
add DWORD PTR [b], %EAX
ret
instead of:
plus3:
mov %EAX, DWORD PTR [%ESP + 4]
shl %EAX, 17
mov %ECX, DWORD PTR [b]
add %EAX, %ECX
and %EAX, -131072
and %ECX, 131071
or %ECX, %EAX
mov DWORD PTR [b], %ECX
ret
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23384 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-18 06:02:59 +00:00
|
|
|
// If we have: ((V + N) & C1) | (V & C2)
|
|
|
|
// .. and C2 = ~C1 and C2 is 0+1+ and (N & C2) == 0
|
|
|
|
// replace with V+N.
|
|
|
|
if (C1 == ConstantExpr::getNot(C2)) {
|
2006-01-06 17:59:59 +00:00
|
|
|
Value *V1 = 0, *V2 = 0;
|
Generalize this transform, using MaskedValueIsZero, allowing us to compile:
struct S { unsigned int i : 6, j : 11, k : 15; } b;
void plus3 (unsigned int x) { b.k += x; }
To:
plus3:
mov %EAX, DWORD PTR [%ESP + 4]
shl %EAX, 17
add DWORD PTR [b], %EAX
ret
instead of:
plus3:
mov %EAX, DWORD PTR [%ESP + 4]
shl %EAX, 17
mov %ECX, DWORD PTR [b]
add %EAX, %ECX
and %EAX, -131072
and %ECX, 131071
or %ECX, %EAX
mov DWORD PTR [b], %ECX
ret
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23384 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-18 06:02:59 +00:00
|
|
|
if ((C2->getRawValue() & (C2->getRawValue()+1)) == 0 && // C2 == 0+1+
|
|
|
|
match(A, m_Add(m_Value(V1), m_Value(V2)))) {
|
|
|
|
// Add commutes, try both ways.
|
2006-02-07 07:27:52 +00:00
|
|
|
if (V1 == B && MaskedValueIsZero(V2, C2->getZExtValue()))
|
Generalize this transform, using MaskedValueIsZero, allowing us to compile:
struct S { unsigned int i : 6, j : 11, k : 15; } b;
void plus3 (unsigned int x) { b.k += x; }
To:
plus3:
mov %EAX, DWORD PTR [%ESP + 4]
shl %EAX, 17
add DWORD PTR [b], %EAX
ret
instead of:
plus3:
mov %EAX, DWORD PTR [%ESP + 4]
shl %EAX, 17
mov %ECX, DWORD PTR [b]
add %EAX, %ECX
and %EAX, -131072
and %ECX, 131071
or %ECX, %EAX
mov DWORD PTR [b], %ECX
ret
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23384 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-18 06:02:59 +00:00
|
|
|
return ReplaceInstUsesWith(I, A);
|
2006-02-07 07:27:52 +00:00
|
|
|
if (V2 == B && MaskedValueIsZero(V1, C2->getZExtValue()))
|
Generalize this transform, using MaskedValueIsZero, allowing us to compile:
struct S { unsigned int i : 6, j : 11, k : 15; } b;
void plus3 (unsigned int x) { b.k += x; }
To:
plus3:
mov %EAX, DWORD PTR [%ESP + 4]
shl %EAX, 17
add DWORD PTR [b], %EAX
ret
instead of:
plus3:
mov %EAX, DWORD PTR [%ESP + 4]
shl %EAX, 17
mov %ECX, DWORD PTR [b]
add %EAX, %ECX
and %EAX, -131072
and %ECX, 131071
or %ECX, %EAX
mov DWORD PTR [b], %ECX
ret
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23384 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-18 06:02:59 +00:00
|
|
|
return ReplaceInstUsesWith(I, A);
|
|
|
|
}
|
|
|
|
// Or commutes, try both ways.
|
|
|
|
if ((C1->getRawValue() & (C1->getRawValue()+1)) == 0 &&
|
|
|
|
match(B, m_Add(m_Value(V1), m_Value(V2)))) {
|
|
|
|
// Add commutes, try both ways.
|
2006-02-07 07:27:52 +00:00
|
|
|
if (V1 == A && MaskedValueIsZero(V2, C1->getZExtValue()))
|
Generalize this transform, using MaskedValueIsZero, allowing us to compile:
struct S { unsigned int i : 6, j : 11, k : 15; } b;
void plus3 (unsigned int x) { b.k += x; }
To:
plus3:
mov %EAX, DWORD PTR [%ESP + 4]
shl %EAX, 17
add DWORD PTR [b], %EAX
ret
instead of:
plus3:
mov %EAX, DWORD PTR [%ESP + 4]
shl %EAX, 17
mov %ECX, DWORD PTR [b]
add %EAX, %ECX
and %EAX, -131072
and %ECX, 131071
or %ECX, %EAX
mov DWORD PTR [b], %ECX
ret
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23384 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-18 06:02:59 +00:00
|
|
|
return ReplaceInstUsesWith(I, B);
|
2006-02-07 07:27:52 +00:00
|
|
|
if (V2 == A && MaskedValueIsZero(V1, C1->getZExtValue()))
|
Generalize this transform, using MaskedValueIsZero, allowing us to compile:
struct S { unsigned int i : 6, j : 11, k : 15; } b;
void plus3 (unsigned int x) { b.k += x; }
To:
plus3:
mov %EAX, DWORD PTR [%ESP + 4]
shl %EAX, 17
add DWORD PTR [b], %EAX
ret
instead of:
plus3:
mov %EAX, DWORD PTR [%ESP + 4]
shl %EAX, 17
mov %ECX, DWORD PTR [b]
add %EAX, %ECX
and %EAX, -131072
and %ECX, 131071
or %ECX, %EAX
mov DWORD PTR [b], %ECX
ret
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23384 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-18 06:02:59 +00:00
|
|
|
return ReplaceInstUsesWith(I, B);
|
2005-09-18 03:42:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-07-30 07:50:03 +00:00
|
|
|
|
|
|
|
if (match(Op0, m_Not(m_Value(A)))) { // ~A | Op1
|
|
|
|
if (A == Op1) // ~A | A == -1
|
2005-04-21 23:48:37 +00:00
|
|
|
return ReplaceInstUsesWith(I,
|
2004-07-30 07:50:03 +00:00
|
|
|
ConstantIntegral::getAllOnesValue(I.getType()));
|
|
|
|
} else {
|
|
|
|
A = 0;
|
|
|
|
}
|
2005-05-07 23:49:08 +00:00
|
|
|
// Note, A is still live here!
|
2004-07-30 07:50:03 +00:00
|
|
|
if (match(Op1, m_Not(m_Value(B)))) { // Op0 | ~B
|
|
|
|
if (Op0 == B)
|
2005-04-21 23:48:37 +00:00
|
|
|
return ReplaceInstUsesWith(I,
|
2004-07-30 07:50:03 +00:00
|
|
|
ConstantIntegral::getAllOnesValue(I.getType()));
|
2003-03-10 23:13:59 +00:00
|
|
|
|
2004-07-30 12:50:08 +00:00
|
|
|
// (~A | ~B) == (~(A & B)) - De Morgan's Law
|
2004-07-30 07:50:03 +00:00
|
|
|
if (A && isOnlyUse(Op0) && isOnlyUse(Op1)) {
|
|
|
|
Value *And = InsertNewInstBefore(BinaryOperator::createAnd(A, B,
|
|
|
|
I.getName()+".demorgan"), I);
|
|
|
|
return BinaryOperator::createNot(And);
|
|
|
|
}
|
2003-03-10 23:13:59 +00:00
|
|
|
}
|
2003-02-18 19:28:33 +00:00
|
|
|
|
2003-08-13 20:16:26 +00:00
|
|
|
// (setcc1 A, B) | (setcc2 A, B) --> (setcc3 A, B)
|
2004-09-28 22:33:08 +00:00
|
|
|
if (SetCondInst *RHS = dyn_cast<SetCondInst>(I.getOperand(1))) {
|
2003-08-13 20:16:26 +00:00
|
|
|
if (Instruction *R = AssociativeOpt(I, FoldSetCCLogical(*this, RHS)))
|
|
|
|
return R;
|
|
|
|
|
2004-09-28 22:33:08 +00:00
|
|
|
Value *LHSVal, *RHSVal;
|
|
|
|
ConstantInt *LHSCst, *RHSCst;
|
|
|
|
Instruction::BinaryOps LHSCC, RHSCC;
|
|
|
|
if (match(Op0, m_SetCond(LHSCC, m_Value(LHSVal), m_ConstantInt(LHSCst))))
|
|
|
|
if (match(RHS, m_SetCond(RHSCC, m_Value(RHSVal), m_ConstantInt(RHSCst))))
|
|
|
|
if (LHSVal == RHSVal && // Found (X setcc C1) | (X setcc C2)
|
|
|
|
// Set[GL]E X, CST is folded to Set[GL]T elsewhere.
|
2005-04-21 23:48:37 +00:00
|
|
|
LHSCC != Instruction::SetGE && LHSCC != Instruction::SetLE &&
|
2004-09-28 22:33:08 +00:00
|
|
|
RHSCC != Instruction::SetGE && RHSCC != Instruction::SetLE) {
|
|
|
|
// Ensure that the larger constant is on the RHS.
|
|
|
|
Constant *Cmp = ConstantExpr::getSetGT(LHSCst, RHSCst);
|
|
|
|
SetCondInst *LHS = cast<SetCondInst>(Op0);
|
|
|
|
if (cast<ConstantBool>(Cmp)->getValue()) {
|
|
|
|
std::swap(LHS, RHS);
|
|
|
|
std::swap(LHSCst, RHSCst);
|
|
|
|
std::swap(LHSCC, RHSCC);
|
|
|
|
}
|
|
|
|
|
|
|
|
// At this point, we know we have have two setcc instructions
|
|
|
|
// comparing a value against two constants and or'ing the result
|
|
|
|
// together. Because of the above check, we know that we only have
|
|
|
|
// SetEQ, SetNE, SetLT, and SetGT here. We also know (from the
|
|
|
|
// FoldSetCCLogical check above), that the two constants are not
|
|
|
|
// equal.
|
|
|
|
assert(LHSCst != RHSCst && "Compares not folded above?");
|
|
|
|
|
|
|
|
switch (LHSCC) {
|
|
|
|
default: assert(0 && "Unknown integer condition code!");
|
|
|
|
case Instruction::SetEQ:
|
|
|
|
switch (RHSCC) {
|
|
|
|
default: assert(0 && "Unknown integer condition code!");
|
|
|
|
case Instruction::SetEQ:
|
|
|
|
if (LHSCst == SubOne(RHSCst)) {// (X == 13 | X == 14) -> X-13 <u 2
|
|
|
|
Constant *AddCST = ConstantExpr::getNeg(LHSCst);
|
|
|
|
Instruction *Add = BinaryOperator::createAdd(LHSVal, AddCST,
|
|
|
|
LHSVal->getName()+".off");
|
|
|
|
InsertNewInstBefore(Add, I);
|
|
|
|
const Type *UnsType = Add->getType()->getUnsignedVersion();
|
|
|
|
Value *OffsetVal = InsertCastBefore(Add, UnsType, I);
|
|
|
|
AddCST = ConstantExpr::getSub(AddOne(RHSCst), LHSCst);
|
|
|
|
AddCST = ConstantExpr::getCast(AddCST, UnsType);
|
|
|
|
return new SetCondInst(Instruction::SetLT, OffsetVal, AddCST);
|
|
|
|
}
|
|
|
|
break; // (X == 13 | X == 15) -> no change
|
|
|
|
|
2005-04-19 06:04:18 +00:00
|
|
|
case Instruction::SetGT: // (X == 13 | X > 14) -> no change
|
|
|
|
break;
|
2004-09-28 22:33:08 +00:00
|
|
|
case Instruction::SetNE: // (X == 13 | X != 15) -> X != 15
|
|
|
|
case Instruction::SetLT: // (X == 13 | X < 15) -> X < 15
|
|
|
|
return ReplaceInstUsesWith(I, RHS);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case Instruction::SetNE:
|
|
|
|
switch (RHSCC) {
|
|
|
|
default: assert(0 && "Unknown integer condition code!");
|
|
|
|
case Instruction::SetEQ: // (X != 13 | X == 15) -> X != 13
|
|
|
|
case Instruction::SetGT: // (X != 13 | X > 15) -> X != 13
|
|
|
|
return ReplaceInstUsesWith(I, LHS);
|
|
|
|
case Instruction::SetNE: // (X != 13 | X != 15) -> true
|
2005-06-17 03:59:17 +00:00
|
|
|
case Instruction::SetLT: // (X != 13 | X < 15) -> true
|
2004-09-28 22:33:08 +00:00
|
|
|
return ReplaceInstUsesWith(I, ConstantBool::True);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case Instruction::SetLT:
|
|
|
|
switch (RHSCC) {
|
|
|
|
default: assert(0 && "Unknown integer condition code!");
|
|
|
|
case Instruction::SetEQ: // (X < 13 | X == 14) -> no change
|
|
|
|
break;
|
2004-09-29 17:40:11 +00:00
|
|
|
case Instruction::SetGT: // (X < 13 | X > 15) -> (X-13) > 2
|
|
|
|
return InsertRangeTest(LHSVal, LHSCst, AddOne(RHSCst), false, I);
|
2004-09-28 22:33:08 +00:00
|
|
|
case Instruction::SetNE: // (X < 13 | X != 15) -> X != 15
|
|
|
|
case Instruction::SetLT: // (X < 13 | X < 15) -> X < 15
|
|
|
|
return ReplaceInstUsesWith(I, RHS);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case Instruction::SetGT:
|
|
|
|
switch (RHSCC) {
|
|
|
|
default: assert(0 && "Unknown integer condition code!");
|
|
|
|
case Instruction::SetEQ: // (X > 13 | X == 15) -> X > 13
|
|
|
|
case Instruction::SetGT: // (X > 13 | X > 15) -> X > 13
|
|
|
|
return ReplaceInstUsesWith(I, LHS);
|
|
|
|
case Instruction::SetNE: // (X > 13 | X != 15) -> true
|
|
|
|
case Instruction::SetLT: // (X > 13 | X < 15) -> true
|
|
|
|
return ReplaceInstUsesWith(I, ConstantBool::True);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2006-05-05 06:39:07 +00:00
|
|
|
|
|
|
|
// fold (or (cast A), (cast B)) -> (cast (or A, B))
|
|
|
|
if (CastInst *Op0C = dyn_cast<CastInst>(Op0)) {
|
2006-05-05 20:51:30 +00:00
|
|
|
const Type *SrcTy = Op0C->getOperand(0)->getType();
|
2006-05-05 06:39:07 +00:00
|
|
|
if (CastInst *Op1C = dyn_cast<CastInst>(Op1))
|
2006-05-05 20:51:30 +00:00
|
|
|
if (SrcTy == Op1C->getOperand(0)->getType() && SrcTy->isIntegral() &&
|
2006-05-06 09:00:16 +00:00
|
|
|
// Only do this if the casts both really cause code to be generated.
|
|
|
|
ValueRequiresCast(Op0C->getOperand(0), I.getType(), TD) &&
|
|
|
|
ValueRequiresCast(Op1C->getOperand(0), I.getType(), TD)) {
|
2006-05-05 06:39:07 +00:00
|
|
|
Instruction *NewOp = BinaryOperator::createOr(Op0C->getOperand(0),
|
|
|
|
Op1C->getOperand(0),
|
|
|
|
I.getName());
|
|
|
|
InsertNewInstBefore(NewOp, I);
|
|
|
|
return new CastInst(NewOp, I.getType());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-09-18 03:42:07 +00:00
|
|
|
|
2002-06-25 16:13:24 +00:00
|
|
|
return Changed ? &I : 0;
|
2002-05-06 16:14:14 +00:00
|
|
|
}
|
|
|
|
|
2004-02-16 01:20:27 +00:00
|
|
|
// XorSelf - Implements: X ^ X --> 0
|
|
|
|
struct XorSelf {
|
|
|
|
Value *RHS;
|
|
|
|
XorSelf(Value *rhs) : RHS(rhs) {}
|
|
|
|
bool shouldApply(Value *LHS) const { return LHS == RHS; }
|
|
|
|
Instruction *apply(BinaryOperator &Xor) const {
|
|
|
|
return &Xor;
|
|
|
|
}
|
|
|
|
};
|
2002-05-06 16:14:14 +00:00
|
|
|
|
|
|
|
|
2002-06-25 16:13:24 +00:00
|
|
|
Instruction *InstCombiner::visitXor(BinaryOperator &I) {
|
2003-03-10 21:43:22 +00:00
|
|
|
bool Changed = SimplifyCommutative(I);
|
2002-06-25 16:13:24 +00:00
|
|
|
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
2002-05-06 16:14:14 +00:00
|
|
|
|
2004-10-16 18:11:37 +00:00
|
|
|
if (isa<UndefValue>(Op1))
|
|
|
|
return ReplaceInstUsesWith(I, Op1); // X ^ undef -> undef
|
|
|
|
|
2004-02-16 01:20:27 +00:00
|
|
|
// xor X, X = 0, even if X is nested in a sequence of Xor's.
|
|
|
|
if (Instruction *Result = AssociativeOpt(I, XorSelf(Op1))) {
|
|
|
|
assert(Result == &I && "AssociativeOpt didn't work?");
|
2002-08-12 21:17:25 +00:00
|
|
|
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
|
2004-02-16 01:20:27 +00:00
|
|
|
}
|
2006-02-12 08:02:11 +00:00
|
|
|
|
|
|
|
// See if we can simplify any instructions used by the instruction whose sole
|
|
|
|
// purpose is to compute bits we don't care about.
|
|
|
|
uint64_t KnownZero, KnownOne;
|
2006-03-25 21:58:26 +00:00
|
|
|
if (!isa<PackedType>(I.getType()) &&
|
|
|
|
SimplifyDemandedBits(&I, I.getType()->getIntegralTypeMask(),
|
2006-02-12 08:02:11 +00:00
|
|
|
KnownZero, KnownOne))
|
|
|
|
return &I;
|
2002-05-06 16:14:14 +00:00
|
|
|
|
2003-07-23 21:37:07 +00:00
|
|
|
if (ConstantIntegral *RHS = dyn_cast<ConstantIntegral>(Op1)) {
|
|
|
|
if (BinaryOperator *Op0I = dyn_cast<BinaryOperator>(Op0)) {
|
2002-08-20 18:24:26 +00:00
|
|
|
// xor (setcc A, B), true = not (setcc A, B) = setncc A, B
|
2003-07-23 21:37:07 +00:00
|
|
|
if (SetCondInst *SCI = dyn_cast<SetCondInst>(Op0I))
|
2003-10-15 16:48:29 +00:00
|
|
|
if (RHS == ConstantBool::True && SCI->hasOneUse())
|
2002-08-20 18:24:26 +00:00
|
|
|
return new SetCondInst(SCI->getInverseCondition(),
|
|
|
|
SCI->getOperand(0), SCI->getOperand(1));
|
2003-11-04 23:50:51 +00:00
|
|
|
|
2003-11-05 01:06:05 +00:00
|
|
|
// ~(c-X) == X-c-1 == X+(-c-1)
|
2004-01-12 19:35:11 +00:00
|
|
|
if (Op0I->getOpcode() == Instruction::Sub && RHS->isAllOnesValue())
|
|
|
|
if (Constant *Op0I0C = dyn_cast<Constant>(Op0I->getOperand(0))) {
|
2004-06-10 02:07:29 +00:00
|
|
|
Constant *NegOp0I0C = ConstantExpr::getNeg(Op0I0C);
|
|
|
|
Constant *ConstantRHS = ConstantExpr::getSub(NegOp0I0C,
|
2004-01-12 19:35:11 +00:00
|
|
|
ConstantInt::get(I.getType(), 1));
|
2004-06-10 02:07:29 +00:00
|
|
|
return BinaryOperator::createAdd(Op0I->getOperand(1), ConstantRHS);
|
2004-01-12 19:35:11 +00:00
|
|
|
}
|
2004-06-18 06:07:51 +00:00
|
|
|
|
|
|
|
// ~(~X & Y) --> (X | ~Y)
|
|
|
|
if (Op0I->getOpcode() == Instruction::And && RHS->isAllOnesValue()) {
|
|
|
|
if (dyn_castNotVal(Op0I->getOperand(1))) Op0I->swapOperands();
|
|
|
|
if (Value *Op0NotVal = dyn_castNotVal(Op0I->getOperand(0))) {
|
|
|
|
Instruction *NotY =
|
2005-04-21 23:48:37 +00:00
|
|
|
BinaryOperator::createNot(Op0I->getOperand(1),
|
2004-06-18 06:07:51 +00:00
|
|
|
Op0I->getOperand(1)->getName()+".not");
|
|
|
|
InsertNewInstBefore(NotY, I);
|
|
|
|
return BinaryOperator::createOr(Op0NotVal, NotY);
|
|
|
|
}
|
|
|
|
}
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2003-07-23 21:37:07 +00:00
|
|
|
if (ConstantInt *Op0CI = dyn_cast<ConstantInt>(Op0I->getOperand(1)))
|
2006-02-12 08:02:11 +00:00
|
|
|
if (Op0I->getOpcode() == Instruction::Add) {
|
2003-11-04 23:37:10 +00:00
|
|
|
// ~(X-c) --> (-c-1)-X
|
2004-01-12 19:35:11 +00:00
|
|
|
if (RHS->isAllOnesValue()) {
|
2004-06-10 02:07:29 +00:00
|
|
|
Constant *NegOp0CI = ConstantExpr::getNeg(Op0CI);
|
|
|
|
return BinaryOperator::createSub(
|
|
|
|
ConstantExpr::getSub(NegOp0CI,
|
2004-01-12 19:35:11 +00:00
|
|
|
ConstantInt::get(I.getType(), 1)),
|
2003-11-04 23:37:10 +00:00
|
|
|
Op0I->getOperand(0));
|
2004-01-12 19:35:11 +00:00
|
|
|
}
|
2006-02-26 19:57:54 +00:00
|
|
|
} else if (Op0I->getOpcode() == Instruction::Or) {
|
|
|
|
// (X|C1)^C2 -> X^(C1|C2) iff X&~C1 == 0
|
|
|
|
if (MaskedValueIsZero(Op0I->getOperand(0), Op0CI->getZExtValue())) {
|
|
|
|
Constant *NewRHS = ConstantExpr::getOr(Op0CI, RHS);
|
|
|
|
// Anything in both C1 and C2 is known to be zero, remove it from
|
|
|
|
// NewRHS.
|
|
|
|
Constant *CommonBits = ConstantExpr::getAnd(Op0CI, RHS);
|
|
|
|
NewRHS = ConstantExpr::getAnd(NewRHS,
|
|
|
|
ConstantExpr::getNot(CommonBits));
|
|
|
|
WorkList.push_back(Op0I);
|
|
|
|
I.setOperand(0, Op0I->getOperand(0));
|
|
|
|
I.setOperand(1, NewRHS);
|
|
|
|
return &I;
|
|
|
|
}
|
2003-07-23 21:37:07 +00:00
|
|
|
}
|
2002-08-20 18:24:26 +00:00
|
|
|
}
|
2004-04-09 19:05:30 +00:00
|
|
|
|
|
|
|
// Try to fold constant and into select arguments.
|
|
|
|
if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
|
2005-01-01 16:22:27 +00:00
|
|
|
if (Instruction *R = FoldOpIntoSelect(I, SI, this))
|
2004-04-09 19:05:30 +00:00
|
|
|
return R;
|
Fold binary expressions and casts into PHI nodes that have all constant inputs.
This takes something like this:
%A = phi int [ 3, %cond_false.0 ], [ 2, %endif.0.i ], [ 2, %endif.1.i ]
%B = div int %tmp.243, 4
and turns it into:
%A = phi int [ 3/4, %cond_false.0 ], [ 2/4, %endif.0.i ], [ 2/4, %endif.1.i ]
which is later simplified (in this case) into %A = 0.
This triggers thousands of times in spec, for example, 269 times in 176.gcc.
This is tested by InstCombine/add.ll:test23 and set.ll:test18.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16582 91177308-0d34-0410-b5e6-96231b3b80d8
2004-09-29 05:07:12 +00:00
|
|
|
if (isa<PHINode>(Op0))
|
|
|
|
if (Instruction *NV = FoldOpIntoPhi(I))
|
|
|
|
return NV;
|
2002-05-06 16:14:14 +00:00
|
|
|
}
|
|
|
|
|
2003-03-10 23:06:50 +00:00
|
|
|
if (Value *X = dyn_castNotVal(Op0)) // ~A ^ A == -1
|
2003-02-18 19:28:33 +00:00
|
|
|
if (X == Op1)
|
|
|
|
return ReplaceInstUsesWith(I,
|
|
|
|
ConstantIntegral::getAllOnesValue(I.getType()));
|
|
|
|
|
2003-03-10 23:06:50 +00:00
|
|
|
if (Value *X = dyn_castNotVal(Op1)) // A ^ ~A == -1
|
2003-02-18 19:28:33 +00:00
|
|
|
if (X == Op0)
|
|
|
|
return ReplaceInstUsesWith(I,
|
|
|
|
ConstantIntegral::getAllOnesValue(I.getType()));
|
|
|
|
|
2006-04-01 08:03:55 +00:00
|
|
|
if (BinaryOperator *Op1I = dyn_cast<BinaryOperator>(Op1))
|
2004-02-16 03:54:20 +00:00
|
|
|
if (Op1I->getOpcode() == Instruction::Or) {
|
2003-03-10 18:24:17 +00:00
|
|
|
if (Op1I->getOperand(0) == Op0) { // B^(B|A) == (A|B)^B
|
2006-04-01 08:03:55 +00:00
|
|
|
Op1I->swapOperands();
|
2003-03-10 18:24:17 +00:00
|
|
|
I.swapOperands();
|
|
|
|
std::swap(Op0, Op1);
|
|
|
|
} else if (Op1I->getOperand(1) == Op0) { // B^(A|B) == (A|B)^B
|
2006-04-01 08:03:55 +00:00
|
|
|
I.swapOperands(); // Simplified below.
|
2003-03-10 18:24:17 +00:00
|
|
|
std::swap(Op0, Op1);
|
2005-04-21 23:48:37 +00:00
|
|
|
}
|
2004-02-16 03:54:20 +00:00
|
|
|
} else if (Op1I->getOpcode() == Instruction::Xor) {
|
|
|
|
if (Op0 == Op1I->getOperand(0)) // A^(A^B) == B
|
|
|
|
return ReplaceInstUsesWith(I, Op1I->getOperand(1));
|
|
|
|
else if (Op0 == Op1I->getOperand(1)) // A^(B^A) == B
|
|
|
|
return ReplaceInstUsesWith(I, Op1I->getOperand(0));
|
2006-04-01 08:03:55 +00:00
|
|
|
} else if (Op1I->getOpcode() == Instruction::And && Op1I->hasOneUse()) {
|
|
|
|
if (Op1I->getOperand(0) == Op0) // A^(A&B) -> A^(B&A)
|
|
|
|
Op1I->swapOperands();
|
|
|
|
if (Op0 == Op1I->getOperand(1)) { // A^(B&A) -> (B&A)^A
|
|
|
|
I.swapOperands(); // Simplified below.
|
|
|
|
std::swap(Op0, Op1);
|
|
|
|
}
|
2004-02-16 03:54:20 +00:00
|
|
|
}
|
2003-03-10 18:24:17 +00:00
|
|
|
|
2006-04-01 08:03:55 +00:00
|
|
|
if (BinaryOperator *Op0I = dyn_cast<BinaryOperator>(Op0))
|
2003-10-15 16:48:29 +00:00
|
|
|
if (Op0I->getOpcode() == Instruction::Or && Op0I->hasOneUse()) {
|
2003-03-10 18:24:17 +00:00
|
|
|
if (Op0I->getOperand(0) == Op1) // (B|A)^B == (A|B)^B
|
2006-04-01 08:03:55 +00:00
|
|
|
Op0I->swapOperands();
|
2003-03-10 21:43:22 +00:00
|
|
|
if (Op0I->getOperand(1) == Op1) { // (A|B)^B == A & ~B
|
2006-04-01 08:03:55 +00:00
|
|
|
Instruction *NotB = BinaryOperator::createNot(Op1, "tmp");
|
|
|
|
InsertNewInstBefore(NotB, I);
|
2004-06-10 02:07:29 +00:00
|
|
|
return BinaryOperator::createAnd(Op0I->getOperand(0), NotB);
|
2003-03-10 18:24:17 +00:00
|
|
|
}
|
2004-02-16 03:54:20 +00:00
|
|
|
} else if (Op0I->getOpcode() == Instruction::Xor) {
|
|
|
|
if (Op1 == Op0I->getOperand(0)) // (A^B)^A == B
|
|
|
|
return ReplaceInstUsesWith(I, Op0I->getOperand(1));
|
|
|
|
else if (Op1 == Op0I->getOperand(1)) // (B^A)^A == B
|
|
|
|
return ReplaceInstUsesWith(I, Op0I->getOperand(0));
|
2006-04-01 08:03:55 +00:00
|
|
|
} else if (Op0I->getOpcode() == Instruction::And && Op0I->hasOneUse()) {
|
|
|
|
if (Op0I->getOperand(0) == Op1) // (A&B)^A -> (B&A)^A
|
|
|
|
Op0I->swapOperands();
|
2006-04-01 22:05:01 +00:00
|
|
|
if (Op0I->getOperand(1) == Op1 && // (B&A)^A == ~B & A
|
|
|
|
!isa<ConstantInt>(Op1)) { // Canonical form is (B&C)^C
|
2006-04-01 08:03:55 +00:00
|
|
|
Instruction *N = BinaryOperator::createNot(Op0I->getOperand(0), "tmp");
|
|
|
|
InsertNewInstBefore(N, I);
|
|
|
|
return BinaryOperator::createAnd(N, Op1);
|
|
|
|
}
|
2003-03-10 18:24:17 +00:00
|
|
|
}
|
|
|
|
|
2003-08-13 20:16:26 +00:00
|
|
|
// (setcc1 A, B) ^ (setcc2 A, B) --> (setcc3 A, B)
|
|
|
|
if (SetCondInst *RHS = dyn_cast<SetCondInst>(I.getOperand(1)))
|
|
|
|
if (Instruction *R = AssociativeOpt(I, FoldSetCCLogical(*this, RHS)))
|
|
|
|
return R;
|
|
|
|
|
2006-05-05 06:39:07 +00:00
|
|
|
// fold (xor (cast A), (cast B)) -> (cast (xor A, B))
|
|
|
|
if (CastInst *Op0C = dyn_cast<CastInst>(Op0)) {
|
2006-05-05 20:51:30 +00:00
|
|
|
const Type *SrcTy = Op0C->getOperand(0)->getType();
|
2006-05-05 06:39:07 +00:00
|
|
|
if (CastInst *Op1C = dyn_cast<CastInst>(Op1))
|
2006-05-05 20:51:30 +00:00
|
|
|
if (SrcTy == Op1C->getOperand(0)->getType() && SrcTy->isIntegral() &&
|
2006-05-06 09:00:16 +00:00
|
|
|
// Only do this if the casts both really cause code to be generated.
|
|
|
|
ValueRequiresCast(Op0C->getOperand(0), I.getType(), TD) &&
|
|
|
|
ValueRequiresCast(Op1C->getOperand(0), I.getType(), TD)) {
|
2006-05-05 06:39:07 +00:00
|
|
|
Instruction *NewOp = BinaryOperator::createXor(Op0C->getOperand(0),
|
|
|
|
Op1C->getOperand(0),
|
|
|
|
I.getName());
|
|
|
|
InsertNewInstBefore(NewOp, I);
|
|
|
|
return new CastInst(NewOp, I.getType());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-06-25 16:13:24 +00:00
|
|
|
return Changed ? &I : 0;
|
2002-05-06 16:14:14 +00:00
|
|
|
}
|
|
|
|
|
2004-09-29 17:40:11 +00:00
|
|
|
/// MulWithOverflow - Compute Result = In1*In2, returning true if the result
|
|
|
|
/// overflowed for this type.
|
|
|
|
static bool MulWithOverflow(ConstantInt *&Result, ConstantInt *In1,
|
|
|
|
ConstantInt *In2) {
|
|
|
|
Result = cast<ConstantInt>(ConstantExpr::getMul(In1, In2));
|
|
|
|
return !In2->isNullValue() && ConstantExpr::getDiv(Result, In2) != In1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool isPositive(ConstantInt *C) {
|
|
|
|
return cast<ConstantSInt>(C)->getValue() >= 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// AddWithOverflow - Compute Result = In1+In2, returning true if the result
|
|
|
|
/// overflowed for this type.
|
|
|
|
static bool AddWithOverflow(ConstantInt *&Result, ConstantInt *In1,
|
|
|
|
ConstantInt *In2) {
|
|
|
|
Result = cast<ConstantInt>(ConstantExpr::getAdd(In1, In2));
|
|
|
|
|
|
|
|
if (In1->getType()->isUnsigned())
|
|
|
|
return cast<ConstantUInt>(Result)->getValue() <
|
|
|
|
cast<ConstantUInt>(In1)->getValue();
|
|
|
|
if (isPositive(In1) != isPositive(In2))
|
|
|
|
return false;
|
|
|
|
if (isPositive(In1))
|
|
|
|
return cast<ConstantSInt>(Result)->getValue() <
|
|
|
|
cast<ConstantSInt>(In1)->getValue();
|
|
|
|
return cast<ConstantSInt>(Result)->getValue() >
|
|
|
|
cast<ConstantSInt>(In1)->getValue();
|
|
|
|
}
|
|
|
|
|
2005-01-13 20:14:25 +00:00
|
|
|
/// EmitGEPOffset - Given a getelementptr instruction/constantexpr, emit the
|
|
|
|
/// code necessary to compute the offset from the base pointer (without adding
|
|
|
|
/// in the base pointer). Return the result as a signed integer of intptr size.
|
|
|
|
static Value *EmitGEPOffset(User *GEP, Instruction &I, InstCombiner &IC) {
|
|
|
|
TargetData &TD = IC.getTargetData();
|
|
|
|
gep_type_iterator GTI = gep_type_begin(GEP);
|
|
|
|
const Type *UIntPtrTy = TD.getIntPtrType();
|
|
|
|
const Type *SIntPtrTy = UIntPtrTy->getSignedVersion();
|
|
|
|
Value *Result = Constant::getNullValue(SIntPtrTy);
|
|
|
|
|
|
|
|
// Build a mask for high order bits.
|
2006-02-07 07:00:41 +00:00
|
|
|
uint64_t PtrSizeMask = ~0ULL >> (64-TD.getPointerSize()*8);
|
2005-01-13 20:14:25 +00:00
|
|
|
|
|
|
|
for (unsigned i = 1, e = GEP->getNumOperands(); i != e; ++i, ++GTI) {
|
|
|
|
Value *Op = GEP->getOperand(i);
|
2005-01-13 23:26:48 +00:00
|
|
|
uint64_t Size = TD.getTypeSize(GTI.getIndexedType()) & PtrSizeMask;
|
2005-01-13 20:14:25 +00:00
|
|
|
Constant *Scale = ConstantExpr::getCast(ConstantUInt::get(UIntPtrTy, Size),
|
|
|
|
SIntPtrTy);
|
|
|
|
if (Constant *OpC = dyn_cast<Constant>(Op)) {
|
|
|
|
if (!OpC->isNullValue()) {
|
2005-01-13 20:40:58 +00:00
|
|
|
OpC = ConstantExpr::getCast(OpC, SIntPtrTy);
|
2005-01-13 20:14:25 +00:00
|
|
|
Scale = ConstantExpr::getMul(OpC, Scale);
|
|
|
|
if (Constant *RC = dyn_cast<Constant>(Result))
|
|
|
|
Result = ConstantExpr::getAdd(RC, Scale);
|
|
|
|
else {
|
|
|
|
// Emit an add instruction.
|
|
|
|
Result = IC.InsertNewInstBefore(
|
|
|
|
BinaryOperator::createAdd(Result, Scale,
|
|
|
|
GEP->getName()+".offs"), I);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2005-01-14 17:17:59 +00:00
|
|
|
// Convert to correct type.
|
|
|
|
Op = IC.InsertNewInstBefore(new CastInst(Op, SIntPtrTy,
|
|
|
|
Op->getName()+".c"), I);
|
|
|
|
if (Size != 1)
|
2005-01-13 20:40:58 +00:00
|
|
|
// We'll let instcombine(mul) convert this to a shl if possible.
|
|
|
|
Op = IC.InsertNewInstBefore(BinaryOperator::createMul(Op, Scale,
|
|
|
|
GEP->getName()+".idx"), I);
|
2005-01-13 20:14:25 +00:00
|
|
|
|
|
|
|
// Emit an add instruction.
|
2005-01-13 20:40:58 +00:00
|
|
|
Result = IC.InsertNewInstBefore(BinaryOperator::createAdd(Op, Result,
|
2005-01-13 20:14:25 +00:00
|
|
|
GEP->getName()+".offs"), I);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// FoldGEPSetCC - Fold comparisons between a GEP instruction and something
|
|
|
|
/// else. At this point we know that the GEP is on the LHS of the comparison.
|
|
|
|
Instruction *InstCombiner::FoldGEPSetCC(User *GEPLHS, Value *RHS,
|
|
|
|
Instruction::BinaryOps Cond,
|
|
|
|
Instruction &I) {
|
|
|
|
assert(dyn_castGetElementPtr(GEPLHS) && "LHS is not a getelementptr!");
|
Implement an optimization for == and != comparisons like this:
_Bool test2(int X, int Y) {
return &arr[X][Y] == arr;
}
instead of generating this:
bool %test2(int %X, int %Y) {
%tmp.3.idx = mul int %X, 160 ; <int> [#uses=1]
%tmp.3.idx1 = shl int %Y, ubyte 2 ; <int> [#uses=1]
%tmp.3.offs2 = sub int 0, %tmp.3.idx ; <int> [#uses=1]
%tmp.7 = seteq int %tmp.3.idx1, %tmp.3.offs2 ; <bool> [#uses=1]
ret bool %tmp.7
}
generate this:
bool %test2(int %X, int %Y) {
seteq int %X, 0 ; <bool>:0 [#uses=1]
seteq int %Y, 0 ; <bool>:1 [#uses=1]
%tmp.7 = and bool %0, %1 ; <bool> [#uses=1]
ret bool %tmp.7
}
This idiom occurs in C++ programs when iterating from begin() to end(),
in a vector or array. For example, we now compile this:
void test(int X, int Y) {
for (int *i = arr; i != arr+100; ++i)
foo(*i);
}
to this:
no_exit: ; preds = %entry, %no_exit
...
%exitcond = seteq uint %indvar.next, 100 ; <bool> [#uses=1]
br bool %exitcond, label %return, label %no_exit
instead of this:
no_exit: ; preds = %entry, %no_exit
...
%inc5 = getelementptr [100 x [40 x int]]* %arr, int 0, int 0, int %inc.rec ; <int*> [#uses=1]
%tmp.8 = seteq int* %inc5, getelementptr ([100 x [40 x int]]* %arr, int 0, int 100, int 0) ; <bool> [#uses=1]
%indvar.next = add uint %indvar, 1 ; <uint> [#uses=1]
br bool %tmp.8, label %return, label %no_exit
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@19536 91177308-0d34-0410-b5e6-96231b3b80d8
2005-01-13 22:25:21 +00:00
|
|
|
|
|
|
|
if (CastInst *CI = dyn_cast<CastInst>(RHS))
|
|
|
|
if (isa<PointerType>(CI->getOperand(0)->getType()))
|
|
|
|
RHS = CI->getOperand(0);
|
|
|
|
|
2005-01-13 20:14:25 +00:00
|
|
|
Value *PtrBase = GEPLHS->getOperand(0);
|
|
|
|
if (PtrBase == RHS) {
|
|
|
|
// As an optimization, we don't actually have to compute the actual value of
|
|
|
|
// OFFSET if this is a seteq or setne comparison, just return whether each
|
|
|
|
// index is zero or not.
|
Implement an optimization for == and != comparisons like this:
_Bool test2(int X, int Y) {
return &arr[X][Y] == arr;
}
instead of generating this:
bool %test2(int %X, int %Y) {
%tmp.3.idx = mul int %X, 160 ; <int> [#uses=1]
%tmp.3.idx1 = shl int %Y, ubyte 2 ; <int> [#uses=1]
%tmp.3.offs2 = sub int 0, %tmp.3.idx ; <int> [#uses=1]
%tmp.7 = seteq int %tmp.3.idx1, %tmp.3.offs2 ; <bool> [#uses=1]
ret bool %tmp.7
}
generate this:
bool %test2(int %X, int %Y) {
seteq int %X, 0 ; <bool>:0 [#uses=1]
seteq int %Y, 0 ; <bool>:1 [#uses=1]
%tmp.7 = and bool %0, %1 ; <bool> [#uses=1]
ret bool %tmp.7
}
This idiom occurs in C++ programs when iterating from begin() to end(),
in a vector or array. For example, we now compile this:
void test(int X, int Y) {
for (int *i = arr; i != arr+100; ++i)
foo(*i);
}
to this:
no_exit: ; preds = %entry, %no_exit
...
%exitcond = seteq uint %indvar.next, 100 ; <bool> [#uses=1]
br bool %exitcond, label %return, label %no_exit
instead of this:
no_exit: ; preds = %entry, %no_exit
...
%inc5 = getelementptr [100 x [40 x int]]* %arr, int 0, int 0, int %inc.rec ; <int*> [#uses=1]
%tmp.8 = seteq int* %inc5, getelementptr ([100 x [40 x int]]* %arr, int 0, int 100, int 0) ; <bool> [#uses=1]
%indvar.next = add uint %indvar, 1 ; <uint> [#uses=1]
br bool %tmp.8, label %return, label %no_exit
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@19536 91177308-0d34-0410-b5e6-96231b3b80d8
2005-01-13 22:25:21 +00:00
|
|
|
if (Cond == Instruction::SetEQ || Cond == Instruction::SetNE) {
|
|
|
|
Instruction *InVal = 0;
|
2005-01-28 19:32:01 +00:00
|
|
|
gep_type_iterator GTI = gep_type_begin(GEPLHS);
|
|
|
|
for (unsigned i = 1, e = GEPLHS->getNumOperands(); i != e; ++i, ++GTI) {
|
Implement an optimization for == and != comparisons like this:
_Bool test2(int X, int Y) {
return &arr[X][Y] == arr;
}
instead of generating this:
bool %test2(int %X, int %Y) {
%tmp.3.idx = mul int %X, 160 ; <int> [#uses=1]
%tmp.3.idx1 = shl int %Y, ubyte 2 ; <int> [#uses=1]
%tmp.3.offs2 = sub int 0, %tmp.3.idx ; <int> [#uses=1]
%tmp.7 = seteq int %tmp.3.idx1, %tmp.3.offs2 ; <bool> [#uses=1]
ret bool %tmp.7
}
generate this:
bool %test2(int %X, int %Y) {
seteq int %X, 0 ; <bool>:0 [#uses=1]
seteq int %Y, 0 ; <bool>:1 [#uses=1]
%tmp.7 = and bool %0, %1 ; <bool> [#uses=1]
ret bool %tmp.7
}
This idiom occurs in C++ programs when iterating from begin() to end(),
in a vector or array. For example, we now compile this:
void test(int X, int Y) {
for (int *i = arr; i != arr+100; ++i)
foo(*i);
}
to this:
no_exit: ; preds = %entry, %no_exit
...
%exitcond = seteq uint %indvar.next, 100 ; <bool> [#uses=1]
br bool %exitcond, label %return, label %no_exit
instead of this:
no_exit: ; preds = %entry, %no_exit
...
%inc5 = getelementptr [100 x [40 x int]]* %arr, int 0, int 0, int %inc.rec ; <int*> [#uses=1]
%tmp.8 = seteq int* %inc5, getelementptr ([100 x [40 x int]]* %arr, int 0, int 100, int 0) ; <bool> [#uses=1]
%indvar.next = add uint %indvar, 1 ; <uint> [#uses=1]
br bool %tmp.8, label %return, label %no_exit
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@19536 91177308-0d34-0410-b5e6-96231b3b80d8
2005-01-13 22:25:21 +00:00
|
|
|
bool EmitIt = true;
|
|
|
|
if (Constant *C = dyn_cast<Constant>(GEPLHS->getOperand(i))) {
|
|
|
|
if (isa<UndefValue>(C)) // undef index -> undef.
|
|
|
|
return ReplaceInstUsesWith(I, UndefValue::get(I.getType()));
|
|
|
|
if (C->isNullValue())
|
|
|
|
EmitIt = false;
|
2005-01-28 19:32:01 +00:00
|
|
|
else if (TD->getTypeSize(GTI.getIndexedType()) == 0) {
|
|
|
|
EmitIt = false; // This is indexing into a zero sized array?
|
2005-04-21 23:48:37 +00:00
|
|
|
} else if (isa<ConstantInt>(C))
|
Implement an optimization for == and != comparisons like this:
_Bool test2(int X, int Y) {
return &arr[X][Y] == arr;
}
instead of generating this:
bool %test2(int %X, int %Y) {
%tmp.3.idx = mul int %X, 160 ; <int> [#uses=1]
%tmp.3.idx1 = shl int %Y, ubyte 2 ; <int> [#uses=1]
%tmp.3.offs2 = sub int 0, %tmp.3.idx ; <int> [#uses=1]
%tmp.7 = seteq int %tmp.3.idx1, %tmp.3.offs2 ; <bool> [#uses=1]
ret bool %tmp.7
}
generate this:
bool %test2(int %X, int %Y) {
seteq int %X, 0 ; <bool>:0 [#uses=1]
seteq int %Y, 0 ; <bool>:1 [#uses=1]
%tmp.7 = and bool %0, %1 ; <bool> [#uses=1]
ret bool %tmp.7
}
This idiom occurs in C++ programs when iterating from begin() to end(),
in a vector or array. For example, we now compile this:
void test(int X, int Y) {
for (int *i = arr; i != arr+100; ++i)
foo(*i);
}
to this:
no_exit: ; preds = %entry, %no_exit
...
%exitcond = seteq uint %indvar.next, 100 ; <bool> [#uses=1]
br bool %exitcond, label %return, label %no_exit
instead of this:
no_exit: ; preds = %entry, %no_exit
...
%inc5 = getelementptr [100 x [40 x int]]* %arr, int 0, int 0, int %inc.rec ; <int*> [#uses=1]
%tmp.8 = seteq int* %inc5, getelementptr ([100 x [40 x int]]* %arr, int 0, int 100, int 0) ; <bool> [#uses=1]
%indvar.next = add uint %indvar, 1 ; <uint> [#uses=1]
br bool %tmp.8, label %return, label %no_exit
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@19536 91177308-0d34-0410-b5e6-96231b3b80d8
2005-01-13 22:25:21 +00:00
|
|
|
return ReplaceInstUsesWith(I, // No comparison is needed here.
|
|
|
|
ConstantBool::get(Cond == Instruction::SetNE));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (EmitIt) {
|
2005-04-21 23:48:37 +00:00
|
|
|
Instruction *Comp =
|
Implement an optimization for == and != comparisons like this:
_Bool test2(int X, int Y) {
return &arr[X][Y] == arr;
}
instead of generating this:
bool %test2(int %X, int %Y) {
%tmp.3.idx = mul int %X, 160 ; <int> [#uses=1]
%tmp.3.idx1 = shl int %Y, ubyte 2 ; <int> [#uses=1]
%tmp.3.offs2 = sub int 0, %tmp.3.idx ; <int> [#uses=1]
%tmp.7 = seteq int %tmp.3.idx1, %tmp.3.offs2 ; <bool> [#uses=1]
ret bool %tmp.7
}
generate this:
bool %test2(int %X, int %Y) {
seteq int %X, 0 ; <bool>:0 [#uses=1]
seteq int %Y, 0 ; <bool>:1 [#uses=1]
%tmp.7 = and bool %0, %1 ; <bool> [#uses=1]
ret bool %tmp.7
}
This idiom occurs in C++ programs when iterating from begin() to end(),
in a vector or array. For example, we now compile this:
void test(int X, int Y) {
for (int *i = arr; i != arr+100; ++i)
foo(*i);
}
to this:
no_exit: ; preds = %entry, %no_exit
...
%exitcond = seteq uint %indvar.next, 100 ; <bool> [#uses=1]
br bool %exitcond, label %return, label %no_exit
instead of this:
no_exit: ; preds = %entry, %no_exit
...
%inc5 = getelementptr [100 x [40 x int]]* %arr, int 0, int 0, int %inc.rec ; <int*> [#uses=1]
%tmp.8 = seteq int* %inc5, getelementptr ([100 x [40 x int]]* %arr, int 0, int 100, int 0) ; <bool> [#uses=1]
%indvar.next = add uint %indvar, 1 ; <uint> [#uses=1]
br bool %tmp.8, label %return, label %no_exit
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@19536 91177308-0d34-0410-b5e6-96231b3b80d8
2005-01-13 22:25:21 +00:00
|
|
|
new SetCondInst(Cond, GEPLHS->getOperand(i),
|
|
|
|
Constant::getNullValue(GEPLHS->getOperand(i)->getType()));
|
|
|
|
if (InVal == 0)
|
|
|
|
InVal = Comp;
|
|
|
|
else {
|
|
|
|
InVal = InsertNewInstBefore(InVal, I);
|
|
|
|
InsertNewInstBefore(Comp, I);
|
|
|
|
if (Cond == Instruction::SetNE) // True if any are unequal
|
|
|
|
InVal = BinaryOperator::createOr(InVal, Comp);
|
|
|
|
else // True if all are equal
|
|
|
|
InVal = BinaryOperator::createAnd(InVal, Comp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (InVal)
|
|
|
|
return InVal;
|
|
|
|
else
|
|
|
|
ReplaceInstUsesWith(I, // No comparison is needed here, all indexes = 0
|
|
|
|
ConstantBool::get(Cond == Instruction::SetEQ));
|
|
|
|
}
|
2005-01-13 20:14:25 +00:00
|
|
|
|
|
|
|
// Only lower this if the setcc is the only user of the GEP or if we expect
|
|
|
|
// the result to fold to a constant!
|
|
|
|
if (isa<ConstantExpr>(GEPLHS) || GEPLHS->hasOneUse()) {
|
|
|
|
// ((gep Ptr, OFFSET) cmp Ptr) ---> (OFFSET cmp 0).
|
|
|
|
Value *Offset = EmitGEPOffset(GEPLHS, I, *this);
|
|
|
|
return new SetCondInst(Cond, Offset,
|
|
|
|
Constant::getNullValue(Offset->getType()));
|
|
|
|
}
|
|
|
|
} else if (User *GEPRHS = dyn_castGetElementPtr(RHS)) {
|
2005-04-25 20:17:30 +00:00
|
|
|
// If the base pointers are different, but the indices are the same, just
|
|
|
|
// compare the base pointer.
|
|
|
|
if (PtrBase != GEPRHS->getOperand(0)) {
|
|
|
|
bool IndicesTheSame = GEPLHS->getNumOperands()==GEPRHS->getNumOperands();
|
2005-07-27 06:12:32 +00:00
|
|
|
IndicesTheSame &= GEPLHS->getOperand(0)->getType() ==
|
2005-04-26 14:40:41 +00:00
|
|
|
GEPRHS->getOperand(0)->getType();
|
2005-04-25 20:17:30 +00:00
|
|
|
if (IndicesTheSame)
|
|
|
|
for (unsigned i = 1, e = GEPLHS->getNumOperands(); i != e; ++i)
|
|
|
|
if (GEPLHS->getOperand(i) != GEPRHS->getOperand(i)) {
|
|
|
|
IndicesTheSame = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If all indices are the same, just compare the base pointers.
|
|
|
|
if (IndicesTheSame)
|
|
|
|
return new SetCondInst(Cond, GEPLHS->getOperand(0),
|
|
|
|
GEPRHS->getOperand(0));
|
|
|
|
|
|
|
|
// Otherwise, the base pointers are different and the indices are
|
|
|
|
// different, bail out.
|
2005-01-13 20:14:25 +00:00
|
|
|
return 0;
|
2005-04-25 20:17:30 +00:00
|
|
|
}
|
2005-01-13 20:14:25 +00:00
|
|
|
|
Implement an optimization for == and != comparisons like this:
_Bool test2(int X, int Y) {
return &arr[X][Y] == arr;
}
instead of generating this:
bool %test2(int %X, int %Y) {
%tmp.3.idx = mul int %X, 160 ; <int> [#uses=1]
%tmp.3.idx1 = shl int %Y, ubyte 2 ; <int> [#uses=1]
%tmp.3.offs2 = sub int 0, %tmp.3.idx ; <int> [#uses=1]
%tmp.7 = seteq int %tmp.3.idx1, %tmp.3.offs2 ; <bool> [#uses=1]
ret bool %tmp.7
}
generate this:
bool %test2(int %X, int %Y) {
seteq int %X, 0 ; <bool>:0 [#uses=1]
seteq int %Y, 0 ; <bool>:1 [#uses=1]
%tmp.7 = and bool %0, %1 ; <bool> [#uses=1]
ret bool %tmp.7
}
This idiom occurs in C++ programs when iterating from begin() to end(),
in a vector or array. For example, we now compile this:
void test(int X, int Y) {
for (int *i = arr; i != arr+100; ++i)
foo(*i);
}
to this:
no_exit: ; preds = %entry, %no_exit
...
%exitcond = seteq uint %indvar.next, 100 ; <bool> [#uses=1]
br bool %exitcond, label %return, label %no_exit
instead of this:
no_exit: ; preds = %entry, %no_exit
...
%inc5 = getelementptr [100 x [40 x int]]* %arr, int 0, int 0, int %inc.rec ; <int*> [#uses=1]
%tmp.8 = seteq int* %inc5, getelementptr ([100 x [40 x int]]* %arr, int 0, int 100, int 0) ; <bool> [#uses=1]
%indvar.next = add uint %indvar, 1 ; <uint> [#uses=1]
br bool %tmp.8, label %return, label %no_exit
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@19536 91177308-0d34-0410-b5e6-96231b3b80d8
2005-01-13 22:25:21 +00:00
|
|
|
// If one of the GEPs has all zero indices, recurse.
|
|
|
|
bool AllZeros = true;
|
|
|
|
for (unsigned i = 1, e = GEPLHS->getNumOperands(); i != e; ++i)
|
|
|
|
if (!isa<Constant>(GEPLHS->getOperand(i)) ||
|
|
|
|
!cast<Constant>(GEPLHS->getOperand(i))->isNullValue()) {
|
|
|
|
AllZeros = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (AllZeros)
|
|
|
|
return FoldGEPSetCC(GEPRHS, GEPLHS->getOperand(0),
|
|
|
|
SetCondInst::getSwappedCondition(Cond), I);
|
2005-01-14 00:20:05 +00:00
|
|
|
|
|
|
|
// If the other GEP has all zero indices, recurse.
|
Implement an optimization for == and != comparisons like this:
_Bool test2(int X, int Y) {
return &arr[X][Y] == arr;
}
instead of generating this:
bool %test2(int %X, int %Y) {
%tmp.3.idx = mul int %X, 160 ; <int> [#uses=1]
%tmp.3.idx1 = shl int %Y, ubyte 2 ; <int> [#uses=1]
%tmp.3.offs2 = sub int 0, %tmp.3.idx ; <int> [#uses=1]
%tmp.7 = seteq int %tmp.3.idx1, %tmp.3.offs2 ; <bool> [#uses=1]
ret bool %tmp.7
}
generate this:
bool %test2(int %X, int %Y) {
seteq int %X, 0 ; <bool>:0 [#uses=1]
seteq int %Y, 0 ; <bool>:1 [#uses=1]
%tmp.7 = and bool %0, %1 ; <bool> [#uses=1]
ret bool %tmp.7
}
This idiom occurs in C++ programs when iterating from begin() to end(),
in a vector or array. For example, we now compile this:
void test(int X, int Y) {
for (int *i = arr; i != arr+100; ++i)
foo(*i);
}
to this:
no_exit: ; preds = %entry, %no_exit
...
%exitcond = seteq uint %indvar.next, 100 ; <bool> [#uses=1]
br bool %exitcond, label %return, label %no_exit
instead of this:
no_exit: ; preds = %entry, %no_exit
...
%inc5 = getelementptr [100 x [40 x int]]* %arr, int 0, int 0, int %inc.rec ; <int*> [#uses=1]
%tmp.8 = seteq int* %inc5, getelementptr ([100 x [40 x int]]* %arr, int 0, int 100, int 0) ; <bool> [#uses=1]
%indvar.next = add uint %indvar, 1 ; <uint> [#uses=1]
br bool %tmp.8, label %return, label %no_exit
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@19536 91177308-0d34-0410-b5e6-96231b3b80d8
2005-01-13 22:25:21 +00:00
|
|
|
AllZeros = true;
|
|
|
|
for (unsigned i = 1, e = GEPRHS->getNumOperands(); i != e; ++i)
|
|
|
|
if (!isa<Constant>(GEPRHS->getOperand(i)) ||
|
|
|
|
!cast<Constant>(GEPRHS->getOperand(i))->isNullValue()) {
|
|
|
|
AllZeros = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (AllZeros)
|
|
|
|
return FoldGEPSetCC(GEPLHS, GEPRHS->getOperand(0), Cond, I);
|
|
|
|
|
2005-01-14 00:20:05 +00:00
|
|
|
if (GEPLHS->getNumOperands() == GEPRHS->getNumOperands()) {
|
|
|
|
// If the GEPs only differ by one index, compare it.
|
|
|
|
unsigned NumDifferences = 0; // Keep track of # differences.
|
|
|
|
unsigned DiffOperand = 0; // The operand that differs.
|
|
|
|
for (unsigned i = 1, e = GEPRHS->getNumOperands(); i != e; ++i)
|
|
|
|
if (GEPLHS->getOperand(i) != GEPRHS->getOperand(i)) {
|
2005-04-24 06:59:08 +00:00
|
|
|
if (GEPLHS->getOperand(i)->getType()->getPrimitiveSizeInBits() !=
|
|
|
|
GEPRHS->getOperand(i)->getType()->getPrimitiveSizeInBits()) {
|
2005-01-21 23:06:49 +00:00
|
|
|
// Irreconcilable differences.
|
2005-01-14 00:20:05 +00:00
|
|
|
NumDifferences = 2;
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
if (NumDifferences++) break;
|
|
|
|
DiffOperand = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NumDifferences == 0) // SAME GEP?
|
|
|
|
return ReplaceInstUsesWith(I, // No comparison is needed here.
|
|
|
|
ConstantBool::get(Cond == Instruction::SetEQ));
|
|
|
|
else if (NumDifferences == 1) {
|
2005-01-21 23:06:49 +00:00
|
|
|
Value *LHSV = GEPLHS->getOperand(DiffOperand);
|
|
|
|
Value *RHSV = GEPRHS->getOperand(DiffOperand);
|
2005-07-18 23:07:33 +00:00
|
|
|
|
|
|
|
// Convert the operands to signed values to make sure to perform a
|
|
|
|
// signed comparison.
|
|
|
|
const Type *NewTy = LHSV->getType()->getSignedVersion();
|
|
|
|
if (LHSV->getType() != NewTy)
|
|
|
|
LHSV = InsertNewInstBefore(new CastInst(LHSV, NewTy,
|
|
|
|
LHSV->getName()), I);
|
|
|
|
if (RHSV->getType() != NewTy)
|
|
|
|
RHSV = InsertNewInstBefore(new CastInst(RHSV, NewTy,
|
|
|
|
RHSV->getName()), I);
|
|
|
|
return new SetCondInst(Cond, LHSV, RHSV);
|
2005-01-14 00:20:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-01-13 20:14:25 +00:00
|
|
|
// Only lower this if the setcc is the only user of the GEP or if we expect
|
|
|
|
// the result to fold to a constant!
|
|
|
|
if ((isa<ConstantExpr>(GEPLHS) || GEPLHS->hasOneUse()) &&
|
|
|
|
(isa<ConstantExpr>(GEPRHS) || GEPRHS->hasOneUse())) {
|
|
|
|
// ((gep Ptr, OFFSET1) cmp (gep Ptr, OFFSET2) ---> (OFFSET1 cmp OFFSET2)
|
|
|
|
Value *L = EmitGEPOffset(GEPLHS, I, *this);
|
|
|
|
Value *R = EmitGEPOffset(GEPRHS, I, *this);
|
|
|
|
return new SetCondInst(Cond, L, R);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-04-24 06:59:08 +00:00
|
|
|
Instruction *InstCombiner::visitSetCondInst(SetCondInst &I) {
|
2003-03-10 21:43:22 +00:00
|
|
|
bool Changed = SimplifyCommutative(I);
|
2002-08-09 23:47:40 +00:00
|
|
|
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
|
|
|
const Type *Ty = Op0->getType();
|
2002-05-06 16:14:14 +00:00
|
|
|
|
|
|
|
// setcc X, X
|
2002-08-09 23:47:40 +00:00
|
|
|
if (Op0 == Op1)
|
|
|
|
return ReplaceInstUsesWith(I, ConstantBool::get(isTrueWhenEqual(I)));
|
2002-05-09 20:11:54 +00:00
|
|
|
|
2004-10-16 18:11:37 +00:00
|
|
|
if (isa<UndefValue>(Op1)) // X setcc undef -> undef
|
|
|
|
return ReplaceInstUsesWith(I, UndefValue::get(Type::BoolTy));
|
|
|
|
|
2004-11-14 07:33:16 +00:00
|
|
|
// setcc <global/alloca*/null>, <global/alloca*/null> - Global/Stack value
|
|
|
|
// addresses never equal each other! We already know that Op0 != Op1.
|
2005-04-21 23:48:37 +00:00
|
|
|
if ((isa<GlobalValue>(Op0) || isa<AllocaInst>(Op0) ||
|
|
|
|
isa<ConstantPointerNull>(Op0)) &&
|
|
|
|
(isa<GlobalValue>(Op1) || isa<AllocaInst>(Op1) ||
|
2004-11-14 07:33:16 +00:00
|
|
|
isa<ConstantPointerNull>(Op1)))
|
2002-08-09 23:47:40 +00:00
|
|
|
return ReplaceInstUsesWith(I, ConstantBool::get(!isTrueWhenEqual(I)));
|
|
|
|
|
|
|
|
// setcc's with boolean values can always be turned into bitwise operations
|
|
|
|
if (Ty == Type::BoolTy) {
|
2004-08-11 00:50:51 +00:00
|
|
|
switch (I.getOpcode()) {
|
|
|
|
default: assert(0 && "Invalid setcc instruction!");
|
|
|
|
case Instruction::SetEQ: { // seteq bool %A, %B -> ~(A^B)
|
2004-06-10 02:07:29 +00:00
|
|
|
Instruction *Xor = BinaryOperator::createXor(Op0, Op1, I.getName()+"tmp");
|
2002-08-09 23:47:40 +00:00
|
|
|
InsertNewInstBefore(Xor, I);
|
2003-11-03 04:25:02 +00:00
|
|
|
return BinaryOperator::createNot(Xor);
|
2002-08-09 23:47:40 +00:00
|
|
|
}
|
2004-08-11 00:50:51 +00:00
|
|
|
case Instruction::SetNE:
|
|
|
|
return BinaryOperator::createXor(Op0, Op1);
|
2002-08-09 23:47:40 +00:00
|
|
|
|
2004-08-11 00:50:51 +00:00
|
|
|
case Instruction::SetGT:
|
|
|
|
std::swap(Op0, Op1); // Change setgt -> setlt
|
|
|
|
// FALL THROUGH
|
|
|
|
case Instruction::SetLT: { // setlt bool A, B -> ~X & Y
|
|
|
|
Instruction *Not = BinaryOperator::createNot(Op0, I.getName()+"tmp");
|
|
|
|
InsertNewInstBefore(Not, I);
|
|
|
|
return BinaryOperator::createAnd(Not, Op1);
|
|
|
|
}
|
|
|
|
case Instruction::SetGE:
|
2002-08-09 23:47:40 +00:00
|
|
|
std::swap(Op0, Op1); // Change setge -> setle
|
2004-08-11 00:50:51 +00:00
|
|
|
// FALL THROUGH
|
|
|
|
case Instruction::SetLE: { // setle bool %A, %B -> ~A | B
|
|
|
|
Instruction *Not = BinaryOperator::createNot(Op0, I.getName()+"tmp");
|
|
|
|
InsertNewInstBefore(Not, I);
|
|
|
|
return BinaryOperator::createOr(Not, Op1);
|
|
|
|
}
|
|
|
|
}
|
2002-08-09 23:47:40 +00:00
|
|
|
}
|
|
|
|
|
2004-06-09 04:24:29 +00:00
|
|
|
// See if we are doing a comparison between a constant and an instruction that
|
|
|
|
// can be folded into the comparison.
|
2002-08-09 23:47:40 +00:00
|
|
|
if (ConstantInt *CI = dyn_cast<ConstantInt>(Op1)) {
|
2004-09-29 17:40:11 +00:00
|
|
|
// Check to see if we are comparing against the minimum or maximum value...
|
|
|
|
if (CI->isMinValue()) {
|
|
|
|
if (I.getOpcode() == Instruction::SetLT) // A < MIN -> FALSE
|
|
|
|
return ReplaceInstUsesWith(I, ConstantBool::False);
|
|
|
|
if (I.getOpcode() == Instruction::SetGE) // A >= MIN -> TRUE
|
|
|
|
return ReplaceInstUsesWith(I, ConstantBool::True);
|
|
|
|
if (I.getOpcode() == Instruction::SetLE) // A <= MIN -> A == MIN
|
|
|
|
return BinaryOperator::createSetEQ(Op0, Op1);
|
|
|
|
if (I.getOpcode() == Instruction::SetGT) // A > MIN -> A != MIN
|
|
|
|
return BinaryOperator::createSetNE(Op0, Op1);
|
|
|
|
|
|
|
|
} else if (CI->isMaxValue()) {
|
|
|
|
if (I.getOpcode() == Instruction::SetGT) // A > MAX -> FALSE
|
|
|
|
return ReplaceInstUsesWith(I, ConstantBool::False);
|
|
|
|
if (I.getOpcode() == Instruction::SetLE) // A <= MAX -> TRUE
|
|
|
|
return ReplaceInstUsesWith(I, ConstantBool::True);
|
|
|
|
if (I.getOpcode() == Instruction::SetGE) // A >= MAX -> A == MAX
|
|
|
|
return BinaryOperator::createSetEQ(Op0, Op1);
|
|
|
|
if (I.getOpcode() == Instruction::SetLT) // A < MAX -> A != MAX
|
|
|
|
return BinaryOperator::createSetNE(Op0, Op1);
|
|
|
|
|
|
|
|
// Comparing against a value really close to min or max?
|
|
|
|
} else if (isMinValuePlusOne(CI)) {
|
|
|
|
if (I.getOpcode() == Instruction::SetLT) // A < MIN+1 -> A == MIN
|
|
|
|
return BinaryOperator::createSetEQ(Op0, SubOne(CI));
|
|
|
|
if (I.getOpcode() == Instruction::SetGE) // A >= MIN-1 -> A != MIN
|
|
|
|
return BinaryOperator::createSetNE(Op0, SubOne(CI));
|
|
|
|
|
|
|
|
} else if (isMaxValueMinusOne(CI)) {
|
|
|
|
if (I.getOpcode() == Instruction::SetGT) // A > MAX-1 -> A == MAX
|
|
|
|
return BinaryOperator::createSetEQ(Op0, AddOne(CI));
|
|
|
|
if (I.getOpcode() == Instruction::SetLE) // A <= MAX-1 -> A != MAX
|
|
|
|
return BinaryOperator::createSetNE(Op0, AddOne(CI));
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we still have a setle or setge instruction, turn it into the
|
|
|
|
// appropriate setlt or setgt instruction. Since the border cases have
|
|
|
|
// already been handled above, this requires little checking.
|
|
|
|
//
|
|
|
|
if (I.getOpcode() == Instruction::SetLE)
|
|
|
|
return BinaryOperator::createSetLT(Op0, AddOne(CI));
|
|
|
|
if (I.getOpcode() == Instruction::SetGE)
|
|
|
|
return BinaryOperator::createSetGT(Op0, SubOne(CI));
|
|
|
|
|
2006-02-12 02:07:56 +00:00
|
|
|
|
|
|
|
// See if we can fold the comparison based on bits known to be zero or one
|
|
|
|
// in the input.
|
|
|
|
uint64_t KnownZero, KnownOne;
|
|
|
|
if (SimplifyDemandedBits(Op0, Ty->getIntegralTypeMask(),
|
|
|
|
KnownZero, KnownOne, 0))
|
|
|
|
return &I;
|
|
|
|
|
|
|
|
// Given the known and unknown bits, compute a range that the LHS could be
|
|
|
|
// in.
|
|
|
|
if (KnownOne | KnownZero) {
|
|
|
|
if (Ty->isUnsigned()) { // Unsigned comparison.
|
|
|
|
uint64_t Min, Max;
|
|
|
|
uint64_t RHSVal = CI->getZExtValue();
|
|
|
|
ComputeUnsignedMinMaxValuesFromKnownBits(Ty, KnownZero, KnownOne,
|
|
|
|
Min, Max);
|
|
|
|
switch (I.getOpcode()) { // LE/GE have been folded already.
|
|
|
|
default: assert(0 && "Unknown setcc opcode!");
|
|
|
|
case Instruction::SetEQ:
|
|
|
|
if (Max < RHSVal || Min > RHSVal)
|
|
|
|
return ReplaceInstUsesWith(I, ConstantBool::False);
|
|
|
|
break;
|
|
|
|
case Instruction::SetNE:
|
|
|
|
if (Max < RHSVal || Min > RHSVal)
|
|
|
|
return ReplaceInstUsesWith(I, ConstantBool::True);
|
|
|
|
break;
|
|
|
|
case Instruction::SetLT:
|
|
|
|
if (Max < RHSVal) return ReplaceInstUsesWith(I, ConstantBool::True);
|
|
|
|
if (Min > RHSVal) return ReplaceInstUsesWith(I, ConstantBool::False);
|
|
|
|
break;
|
|
|
|
case Instruction::SetGT:
|
|
|
|
if (Min > RHSVal) return ReplaceInstUsesWith(I, ConstantBool::True);
|
|
|
|
if (Max < RHSVal) return ReplaceInstUsesWith(I, ConstantBool::False);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else { // Signed comparison.
|
|
|
|
int64_t Min, Max;
|
|
|
|
int64_t RHSVal = CI->getSExtValue();
|
|
|
|
ComputeSignedMinMaxValuesFromKnownBits(Ty, KnownZero, KnownOne,
|
|
|
|
Min, Max);
|
|
|
|
switch (I.getOpcode()) { // LE/GE have been folded already.
|
|
|
|
default: assert(0 && "Unknown setcc opcode!");
|
|
|
|
case Instruction::SetEQ:
|
|
|
|
if (Max < RHSVal || Min > RHSVal)
|
|
|
|
return ReplaceInstUsesWith(I, ConstantBool::False);
|
|
|
|
break;
|
|
|
|
case Instruction::SetNE:
|
|
|
|
if (Max < RHSVal || Min > RHSVal)
|
|
|
|
return ReplaceInstUsesWith(I, ConstantBool::True);
|
|
|
|
break;
|
|
|
|
case Instruction::SetLT:
|
|
|
|
if (Max < RHSVal) return ReplaceInstUsesWith(I, ConstantBool::True);
|
|
|
|
if (Min > RHSVal) return ReplaceInstUsesWith(I, ConstantBool::False);
|
|
|
|
break;
|
|
|
|
case Instruction::SetGT:
|
|
|
|
if (Min > RHSVal) return ReplaceInstUsesWith(I, ConstantBool::True);
|
|
|
|
if (Max < RHSVal) return ReplaceInstUsesWith(I, ConstantBool::False);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-05-25 06:32:08 +00:00
|
|
|
if (Instruction *LHSI = dyn_cast<Instruction>(Op0))
|
2004-09-23 21:52:49 +00:00
|
|
|
switch (LHSI->getOpcode()) {
|
|
|
|
case Instruction::And:
|
|
|
|
if (LHSI->hasOneUse() && isa<ConstantInt>(LHSI->getOperand(1)) &&
|
|
|
|
LHSI->getOperand(0)->hasOneUse()) {
|
|
|
|
// If this is: (X >> C1) & C2 != C3 (where any shift and any compare
|
|
|
|
// could exist), turn it into (X & (C2 << C1)) != (C3 << C1). This
|
|
|
|
// happens a LOT in code produced by the C front-end, for bitfield
|
|
|
|
// access.
|
|
|
|
ShiftInst *Shift = dyn_cast<ShiftInst>(LHSI->getOperand(0));
|
2006-02-12 02:07:56 +00:00
|
|
|
ConstantInt *AndCST = cast<ConstantInt>(LHSI->getOperand(1));
|
|
|
|
|
|
|
|
// Check to see if there is a noop-cast between the shift and the and.
|
|
|
|
if (!Shift) {
|
|
|
|
if (CastInst *CI = dyn_cast<CastInst>(LHSI->getOperand(0)))
|
|
|
|
if (CI->getOperand(0)->getType()->isIntegral() &&
|
|
|
|
CI->getOperand(0)->getType()->getPrimitiveSizeInBits() ==
|
|
|
|
CI->getType()->getPrimitiveSizeInBits())
|
|
|
|
Shift = dyn_cast<ShiftInst>(CI->getOperand(0));
|
|
|
|
}
|
|
|
|
|
2004-09-23 21:52:49 +00:00
|
|
|
ConstantUInt *ShAmt;
|
|
|
|
ShAmt = Shift ? dyn_cast<ConstantUInt>(Shift->getOperand(1)) : 0;
|
2006-02-12 02:07:56 +00:00
|
|
|
const Type *Ty = Shift ? Shift->getType() : 0; // Type of the shift.
|
|
|
|
const Type *AndTy = AndCST->getType(); // Type of the and.
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2004-09-23 21:52:49 +00:00
|
|
|
// We can fold this as long as we can't shift unknown bits
|
|
|
|
// into the mask. This can only happen with signed shift
|
|
|
|
// rights, as they sign-extend.
|
|
|
|
if (ShAmt) {
|
|
|
|
bool CanFold = Shift->getOpcode() != Instruction::Shr ||
|
2006-02-12 02:07:56 +00:00
|
|
|
Ty->isUnsigned();
|
2004-09-23 21:52:49 +00:00
|
|
|
if (!CanFold) {
|
|
|
|
// To test for the bad case of the signed shr, see if any
|
|
|
|
// of the bits shifted in could be tested after the mask.
|
2005-06-17 01:29:28 +00:00
|
|
|
int ShAmtVal = Ty->getPrimitiveSizeInBits()-ShAmt->getValue();
|
|
|
|
if (ShAmtVal < 0) ShAmtVal = 0; // Out of range shift.
|
|
|
|
|
|
|
|
Constant *OShAmt = ConstantUInt::get(Type::UByteTy, ShAmtVal);
|
2005-04-21 23:48:37 +00:00
|
|
|
Constant *ShVal =
|
2006-02-12 02:07:56 +00:00
|
|
|
ConstantExpr::getShl(ConstantInt::getAllOnesValue(AndTy),
|
|
|
|
OShAmt);
|
2004-09-23 21:52:49 +00:00
|
|
|
if (ConstantExpr::getAnd(ShVal, AndCST)->isNullValue())
|
|
|
|
CanFold = true;
|
|
|
|
}
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2004-09-23 21:52:49 +00:00
|
|
|
if (CanFold) {
|
2004-09-28 17:54:07 +00:00
|
|
|
Constant *NewCst;
|
|
|
|
if (Shift->getOpcode() == Instruction::Shl)
|
|
|
|
NewCst = ConstantExpr::getUShr(CI, ShAmt);
|
|
|
|
else
|
|
|
|
NewCst = ConstantExpr::getShl(CI, ShAmt);
|
2004-09-27 19:29:18 +00:00
|
|
|
|
2004-09-23 21:52:49 +00:00
|
|
|
// Check to see if we are shifting out any of the bits being
|
|
|
|
// compared.
|
|
|
|
if (ConstantExpr::get(Shift->getOpcode(), NewCst, ShAmt) != CI){
|
|
|
|
// If we shifted bits out, the fold is not going to work out.
|
|
|
|
// As a special case, check to see if this means that the
|
|
|
|
// result is always true or false now.
|
|
|
|
if (I.getOpcode() == Instruction::SetEQ)
|
|
|
|
return ReplaceInstUsesWith(I, ConstantBool::False);
|
|
|
|
if (I.getOpcode() == Instruction::SetNE)
|
|
|
|
return ReplaceInstUsesWith(I, ConstantBool::True);
|
|
|
|
} else {
|
|
|
|
I.setOperand(1, NewCst);
|
2004-09-28 17:54:07 +00:00
|
|
|
Constant *NewAndCST;
|
|
|
|
if (Shift->getOpcode() == Instruction::Shl)
|
|
|
|
NewAndCST = ConstantExpr::getUShr(AndCST, ShAmt);
|
|
|
|
else
|
|
|
|
NewAndCST = ConstantExpr::getShl(AndCST, ShAmt);
|
|
|
|
LHSI->setOperand(1, NewAndCST);
|
2006-02-12 02:07:56 +00:00
|
|
|
if (AndTy == Ty)
|
|
|
|
LHSI->setOperand(0, Shift->getOperand(0));
|
|
|
|
else {
|
|
|
|
Value *NewCast = InsertCastBefore(Shift->getOperand(0), AndTy,
|
|
|
|
*Shift);
|
|
|
|
LHSI->setOperand(0, NewCast);
|
|
|
|
}
|
2004-09-23 21:52:49 +00:00
|
|
|
WorkList.push_back(Shift); // Shift is dead.
|
|
|
|
AddUsesToWorkList(I);
|
|
|
|
return &I;
|
2004-07-21 19:50:44 +00:00
|
|
|
}
|
|
|
|
}
|
2004-06-09 07:59:58 +00:00
|
|
|
}
|
2004-09-23 21:52:49 +00:00
|
|
|
}
|
|
|
|
break;
|
2004-09-27 19:29:18 +00:00
|
|
|
|
2004-09-28 18:22:15 +00:00
|
|
|
case Instruction::Shl: // (setcc (shl X, ShAmt), CI)
|
|
|
|
if (ConstantUInt *ShAmt = dyn_cast<ConstantUInt>(LHSI->getOperand(1))) {
|
|
|
|
switch (I.getOpcode()) {
|
|
|
|
default: break;
|
|
|
|
case Instruction::SetEQ:
|
|
|
|
case Instruction::SetNE: {
|
2005-06-15 20:53:31 +00:00
|
|
|
unsigned TypeBits = CI->getType()->getPrimitiveSizeInBits();
|
|
|
|
|
|
|
|
// Check that the shift amount is in range. If not, don't perform
|
|
|
|
// undefined shifts. When the shift is visited it will be
|
|
|
|
// simplified.
|
|
|
|
if (ShAmt->getValue() >= TypeBits)
|
|
|
|
break;
|
|
|
|
|
2004-09-28 18:22:15 +00:00
|
|
|
// If we are comparing against bits always shifted out, the
|
|
|
|
// comparison cannot succeed.
|
2005-04-21 23:48:37 +00:00
|
|
|
Constant *Comp =
|
2004-09-28 18:22:15 +00:00
|
|
|
ConstantExpr::getShl(ConstantExpr::getShr(CI, ShAmt), ShAmt);
|
|
|
|
if (Comp != CI) {// Comparing against a bit that we know is zero.
|
|
|
|
bool IsSetNE = I.getOpcode() == Instruction::SetNE;
|
|
|
|
Constant *Cst = ConstantBool::get(IsSetNE);
|
|
|
|
return ReplaceInstUsesWith(I, Cst);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (LHSI->hasOneUse()) {
|
|
|
|
// Otherwise strength reduce the shift into an and.
|
2005-01-08 19:42:22 +00:00
|
|
|
unsigned ShAmtVal = (unsigned)ShAmt->getValue();
|
2004-09-28 18:22:15 +00:00
|
|
|
uint64_t Val = (1ULL << (TypeBits-ShAmtVal))-1;
|
|
|
|
|
|
|
|
Constant *Mask;
|
|
|
|
if (CI->getType()->isUnsigned()) {
|
|
|
|
Mask = ConstantUInt::get(CI->getType(), Val);
|
|
|
|
} else if (ShAmtVal != 0) {
|
|
|
|
Mask = ConstantSInt::get(CI->getType(), Val);
|
|
|
|
} else {
|
|
|
|
Mask = ConstantInt::getAllOnesValue(CI->getType());
|
|
|
|
}
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2004-09-28 18:22:15 +00:00
|
|
|
Instruction *AndI =
|
|
|
|
BinaryOperator::createAnd(LHSI->getOperand(0),
|
|
|
|
Mask, LHSI->getName()+".mask");
|
|
|
|
Value *And = InsertNewInstBefore(AndI, I);
|
|
|
|
return new SetCondInst(I.getOpcode(), And,
|
|
|
|
ConstantExpr::getUShr(CI, ShAmt));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2004-09-27 19:29:18 +00:00
|
|
|
case Instruction::Shr: // (setcc (shr X, ShAmt), CI)
|
Fold: (setcc (shr X, ShAmt), CI), where 'cc' is eq or ne. This xform
triggers often, for example:
6x in povray, 1x in gzip, 279x in gcc, 1x in crafty, 8x in eon, 11x in perlbmk,
362x in gap, 4x in vortex, 14 in m88ksim, 211x in 126.gcc, 1x in compress,
11x in ijpeg, and 4x in 147.vortex.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16521 91177308-0d34-0410-b5e6-96231b3b80d8
2004-09-27 16:18:50 +00:00
|
|
|
if (ConstantUInt *ShAmt = dyn_cast<ConstantUInt>(LHSI->getOperand(1))) {
|
|
|
|
switch (I.getOpcode()) {
|
|
|
|
default: break;
|
|
|
|
case Instruction::SetEQ:
|
|
|
|
case Instruction::SetNE: {
|
2005-06-15 20:53:31 +00:00
|
|
|
|
|
|
|
// Check that the shift amount is in range. If not, don't perform
|
|
|
|
// undefined shifts. When the shift is visited it will be
|
|
|
|
// simplified.
|
2005-06-16 01:52:07 +00:00
|
|
|
unsigned TypeBits = CI->getType()->getPrimitiveSizeInBits();
|
2005-06-15 20:53:31 +00:00
|
|
|
if (ShAmt->getValue() >= TypeBits)
|
|
|
|
break;
|
|
|
|
|
Fold: (setcc (shr X, ShAmt), CI), where 'cc' is eq or ne. This xform
triggers often, for example:
6x in povray, 1x in gzip, 279x in gcc, 1x in crafty, 8x in eon, 11x in perlbmk,
362x in gap, 4x in vortex, 14 in m88ksim, 211x in 126.gcc, 1x in compress,
11x in ijpeg, and 4x in 147.vortex.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16521 91177308-0d34-0410-b5e6-96231b3b80d8
2004-09-27 16:18:50 +00:00
|
|
|
// If we are comparing against bits always shifted out, the
|
|
|
|
// comparison cannot succeed.
|
2005-04-21 23:48:37 +00:00
|
|
|
Constant *Comp =
|
Fold: (setcc (shr X, ShAmt), CI), where 'cc' is eq or ne. This xform
triggers often, for example:
6x in povray, 1x in gzip, 279x in gcc, 1x in crafty, 8x in eon, 11x in perlbmk,
362x in gap, 4x in vortex, 14 in m88ksim, 211x in 126.gcc, 1x in compress,
11x in ijpeg, and 4x in 147.vortex.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16521 91177308-0d34-0410-b5e6-96231b3b80d8
2004-09-27 16:18:50 +00:00
|
|
|
ConstantExpr::getShr(ConstantExpr::getShl(CI, ShAmt), ShAmt);
|
2005-04-21 23:48:37 +00:00
|
|
|
|
Fold: (setcc (shr X, ShAmt), CI), where 'cc' is eq or ne. This xform
triggers often, for example:
6x in povray, 1x in gzip, 279x in gcc, 1x in crafty, 8x in eon, 11x in perlbmk,
362x in gap, 4x in vortex, 14 in m88ksim, 211x in 126.gcc, 1x in compress,
11x in ijpeg, and 4x in 147.vortex.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16521 91177308-0d34-0410-b5e6-96231b3b80d8
2004-09-27 16:18:50 +00:00
|
|
|
if (Comp != CI) {// Comparing against a bit that we know is zero.
|
|
|
|
bool IsSetNE = I.getOpcode() == Instruction::SetNE;
|
|
|
|
Constant *Cst = ConstantBool::get(IsSetNE);
|
|
|
|
return ReplaceInstUsesWith(I, Cst);
|
|
|
|
}
|
2005-04-21 23:48:37 +00:00
|
|
|
|
Fold: (setcc (shr X, ShAmt), CI), where 'cc' is eq or ne. This xform
triggers often, for example:
6x in povray, 1x in gzip, 279x in gcc, 1x in crafty, 8x in eon, 11x in perlbmk,
362x in gap, 4x in vortex, 14 in m88ksim, 211x in 126.gcc, 1x in compress,
11x in ijpeg, and 4x in 147.vortex.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16521 91177308-0d34-0410-b5e6-96231b3b80d8
2004-09-27 16:18:50 +00:00
|
|
|
if (LHSI->hasOneUse() || CI->isNullValue()) {
|
2005-01-08 19:42:22 +00:00
|
|
|
unsigned ShAmtVal = (unsigned)ShAmt->getValue();
|
2004-09-28 18:22:15 +00:00
|
|
|
|
Fold: (setcc (shr X, ShAmt), CI), where 'cc' is eq or ne. This xform
triggers often, for example:
6x in povray, 1x in gzip, 279x in gcc, 1x in crafty, 8x in eon, 11x in perlbmk,
362x in gap, 4x in vortex, 14 in m88ksim, 211x in 126.gcc, 1x in compress,
11x in ijpeg, and 4x in 147.vortex.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16521 91177308-0d34-0410-b5e6-96231b3b80d8
2004-09-27 16:18:50 +00:00
|
|
|
// Otherwise strength reduce the shift into an and.
|
|
|
|
uint64_t Val = ~0ULL; // All ones.
|
|
|
|
Val <<= ShAmtVal; // Shift over to the right spot.
|
|
|
|
|
|
|
|
Constant *Mask;
|
|
|
|
if (CI->getType()->isUnsigned()) {
|
2005-04-24 17:46:05 +00:00
|
|
|
Val &= ~0ULL >> (64-TypeBits);
|
Fold: (setcc (shr X, ShAmt), CI), where 'cc' is eq or ne. This xform
triggers often, for example:
6x in povray, 1x in gzip, 279x in gcc, 1x in crafty, 8x in eon, 11x in perlbmk,
362x in gap, 4x in vortex, 14 in m88ksim, 211x in 126.gcc, 1x in compress,
11x in ijpeg, and 4x in 147.vortex.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16521 91177308-0d34-0410-b5e6-96231b3b80d8
2004-09-27 16:18:50 +00:00
|
|
|
Mask = ConstantUInt::get(CI->getType(), Val);
|
|
|
|
} else {
|
|
|
|
Mask = ConstantSInt::get(CI->getType(), Val);
|
|
|
|
}
|
2005-04-21 23:48:37 +00:00
|
|
|
|
Fold: (setcc (shr X, ShAmt), CI), where 'cc' is eq or ne. This xform
triggers often, for example:
6x in povray, 1x in gzip, 279x in gcc, 1x in crafty, 8x in eon, 11x in perlbmk,
362x in gap, 4x in vortex, 14 in m88ksim, 211x in 126.gcc, 1x in compress,
11x in ijpeg, and 4x in 147.vortex.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16521 91177308-0d34-0410-b5e6-96231b3b80d8
2004-09-27 16:18:50 +00:00
|
|
|
Instruction *AndI =
|
|
|
|
BinaryOperator::createAnd(LHSI->getOperand(0),
|
|
|
|
Mask, LHSI->getName()+".mask");
|
|
|
|
Value *And = InsertNewInstBefore(AndI, I);
|
|
|
|
return new SetCondInst(I.getOpcode(), And,
|
|
|
|
ConstantExpr::getShl(CI, ShAmt));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2004-09-24 15:21:34 +00:00
|
|
|
|
2004-09-29 17:40:11 +00:00
|
|
|
case Instruction::Div:
|
|
|
|
// Fold: (div X, C1) op C2 -> range check
|
|
|
|
if (ConstantInt *DivRHS = dyn_cast<ConstantInt>(LHSI->getOperand(1))) {
|
|
|
|
// Fold this div into the comparison, producing a range check.
|
|
|
|
// Determine, based on the divide type, what the range is being
|
|
|
|
// checked. If there is an overflow on the low or high side, remember
|
|
|
|
// it, otherwise compute the range [low, hi) bounding the new value.
|
|
|
|
bool LoOverflow = false, HiOverflow = 0;
|
|
|
|
ConstantInt *LoBound = 0, *HiBound = 0;
|
|
|
|
|
|
|
|
ConstantInt *Prod;
|
|
|
|
bool ProdOV = MulWithOverflow(Prod, CI, DivRHS);
|
|
|
|
|
2004-10-11 19:40:04 +00:00
|
|
|
Instruction::BinaryOps Opcode = I.getOpcode();
|
|
|
|
|
2004-09-29 17:40:11 +00:00
|
|
|
if (DivRHS->isNullValue()) { // Don't hack on divide by zeros.
|
|
|
|
} else if (LHSI->getType()->isUnsigned()) { // udiv
|
|
|
|
LoBound = Prod;
|
|
|
|
LoOverflow = ProdOV;
|
|
|
|
HiOverflow = ProdOV || AddWithOverflow(HiBound, LoBound, DivRHS);
|
|
|
|
} else if (isPositive(DivRHS)) { // Divisor is > 0.
|
|
|
|
if (CI->isNullValue()) { // (X / pos) op 0
|
|
|
|
// Can't overflow.
|
|
|
|
LoBound = cast<ConstantInt>(ConstantExpr::getNeg(SubOne(DivRHS)));
|
|
|
|
HiBound = DivRHS;
|
|
|
|
} else if (isPositive(CI)) { // (X / pos) op pos
|
|
|
|
LoBound = Prod;
|
|
|
|
LoOverflow = ProdOV;
|
|
|
|
HiOverflow = ProdOV || AddWithOverflow(HiBound, Prod, DivRHS);
|
|
|
|
} else { // (X / pos) op neg
|
|
|
|
Constant *DivRHSH = ConstantExpr::getNeg(SubOne(DivRHS));
|
|
|
|
LoOverflow = AddWithOverflow(LoBound, Prod,
|
|
|
|
cast<ConstantInt>(DivRHSH));
|
|
|
|
HiBound = Prod;
|
|
|
|
HiOverflow = ProdOV;
|
|
|
|
}
|
|
|
|
} else { // Divisor is < 0.
|
|
|
|
if (CI->isNullValue()) { // (X / neg) op 0
|
|
|
|
LoBound = AddOne(DivRHS);
|
|
|
|
HiBound = cast<ConstantInt>(ConstantExpr::getNeg(DivRHS));
|
2005-06-17 02:05:55 +00:00
|
|
|
if (HiBound == DivRHS)
|
|
|
|
LoBound = 0; // - INTMIN = INTMIN
|
2004-09-29 17:40:11 +00:00
|
|
|
} else if (isPositive(CI)) { // (X / neg) op pos
|
|
|
|
HiOverflow = LoOverflow = ProdOV;
|
|
|
|
if (!LoOverflow)
|
|
|
|
LoOverflow = AddWithOverflow(LoBound, Prod, AddOne(DivRHS));
|
|
|
|
HiBound = AddOne(Prod);
|
|
|
|
} else { // (X / neg) op neg
|
|
|
|
LoBound = Prod;
|
|
|
|
LoOverflow = HiOverflow = ProdOV;
|
|
|
|
HiBound = cast<ConstantInt>(ConstantExpr::getSub(Prod, DivRHS));
|
|
|
|
}
|
2004-10-08 19:15:44 +00:00
|
|
|
|
2004-10-11 19:40:04 +00:00
|
|
|
// Dividing by a negate swaps the condition.
|
|
|
|
Opcode = SetCondInst::getSwappedCondition(Opcode);
|
2004-09-29 17:40:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (LoBound) {
|
|
|
|
Value *X = LHSI->getOperand(0);
|
2004-10-11 19:40:04 +00:00
|
|
|
switch (Opcode) {
|
2004-09-29 17:40:11 +00:00
|
|
|
default: assert(0 && "Unhandled setcc opcode!");
|
|
|
|
case Instruction::SetEQ:
|
|
|
|
if (LoOverflow && HiOverflow)
|
|
|
|
return ReplaceInstUsesWith(I, ConstantBool::False);
|
|
|
|
else if (HiOverflow)
|
|
|
|
return new SetCondInst(Instruction::SetGE, X, LoBound);
|
|
|
|
else if (LoOverflow)
|
|
|
|
return new SetCondInst(Instruction::SetLT, X, HiBound);
|
|
|
|
else
|
|
|
|
return InsertRangeTest(X, LoBound, HiBound, true, I);
|
|
|
|
case Instruction::SetNE:
|
|
|
|
if (LoOverflow && HiOverflow)
|
|
|
|
return ReplaceInstUsesWith(I, ConstantBool::True);
|
|
|
|
else if (HiOverflow)
|
|
|
|
return new SetCondInst(Instruction::SetLT, X, LoBound);
|
|
|
|
else if (LoOverflow)
|
|
|
|
return new SetCondInst(Instruction::SetGE, X, HiBound);
|
|
|
|
else
|
|
|
|
return InsertRangeTest(X, LoBound, HiBound, false, I);
|
|
|
|
case Instruction::SetLT:
|
|
|
|
if (LoOverflow)
|
|
|
|
return ReplaceInstUsesWith(I, ConstantBool::False);
|
|
|
|
return new SetCondInst(Instruction::SetLT, X, LoBound);
|
|
|
|
case Instruction::SetGT:
|
|
|
|
if (HiOverflow)
|
|
|
|
return ReplaceInstUsesWith(I, ConstantBool::False);
|
|
|
|
return new SetCondInst(Instruction::SetGE, X, HiBound);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2004-09-23 21:52:49 +00:00
|
|
|
}
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2003-07-23 17:02:11 +00:00
|
|
|
// Simplify seteq and setne instructions...
|
|
|
|
if (I.getOpcode() == Instruction::SetEQ ||
|
|
|
|
I.getOpcode() == Instruction::SetNE) {
|
|
|
|
bool isSetNE = I.getOpcode() == Instruction::SetNE;
|
|
|
|
|
2003-07-23 17:26:36 +00:00
|
|
|
// If the first operand is (and|or|xor) with a constant, and the second
|
2003-07-23 17:02:11 +00:00
|
|
|
// operand is a constant, simplify a bit.
|
2003-08-13 05:33:12 +00:00
|
|
|
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(Op0)) {
|
|
|
|
switch (BO->getOpcode()) {
|
2004-07-06 07:38:18 +00:00
|
|
|
case Instruction::Rem:
|
|
|
|
// If we have a signed (X % (2^c)) == 0, turn it into an unsigned one.
|
|
|
|
if (CI->isNullValue() && isa<ConstantSInt>(BO->getOperand(1)) &&
|
|
|
|
BO->hasOneUse() &&
|
2005-08-02 19:16:58 +00:00
|
|
|
cast<ConstantSInt>(BO->getOperand(1))->getValue() > 1) {
|
|
|
|
int64_t V = cast<ConstantSInt>(BO->getOperand(1))->getValue();
|
|
|
|
if (isPowerOf2_64(V)) {
|
|
|
|
unsigned L2 = Log2_64(V);
|
2004-07-06 07:38:18 +00:00
|
|
|
const Type *UTy = BO->getType()->getUnsignedVersion();
|
|
|
|
Value *NewX = InsertNewInstBefore(new CastInst(BO->getOperand(0),
|
|
|
|
UTy, "tmp"), I);
|
|
|
|
Constant *RHSCst = ConstantUInt::get(UTy, 1ULL << L2);
|
|
|
|
Value *NewRem =InsertNewInstBefore(BinaryOperator::createRem(NewX,
|
|
|
|
RHSCst, BO->getName()), I);
|
|
|
|
return BinaryOperator::create(I.getOpcode(), NewRem,
|
|
|
|
Constant::getNullValue(UTy));
|
|
|
|
}
|
2005-08-02 19:16:58 +00:00
|
|
|
}
|
2005-04-21 23:48:37 +00:00
|
|
|
break;
|
2004-07-06 07:38:18 +00:00
|
|
|
|
2003-08-13 05:33:12 +00:00
|
|
|
case Instruction::Add:
|
2004-06-27 22:51:36 +00:00
|
|
|
// Replace ((add A, B) != C) with (A != C-B) if B & C are constants.
|
|
|
|
if (ConstantInt *BOp1C = dyn_cast<ConstantInt>(BO->getOperand(1))) {
|
Do not fold (X + C1 != C2) if there are other users of the add. Doing
this transformation used to take a loop like this:
int Array[1000];
void test(int X) {
int i;
for (i = 0; i < 1000; ++i)
Array[i] += X;
}
Compiled to LLVM is:
no_exit: ; preds = %entry, %no_exit
%indvar = phi uint [ 0, %entry ], [ %indvar.next, %no_exit ] ; <uint> [#uses=2]
%tmp.4 = getelementptr [1000 x int]* %Array, int 0, uint %indvar ; <int*> [#uses=2]
%tmp.7 = load int* %tmp.4 ; <int> [#uses=1]
%tmp.9 = add int %tmp.7, %X ; <int> [#uses=1]
store int %tmp.9, int* %tmp.4
*** %indvar.next = add uint %indvar, 1 ; <uint> [#uses=2]
*** %exitcond = seteq uint %indvar.next, 1000 ; <bool> [#uses=1]
br bool %exitcond, label %return, label %no_exit
and turn it into a loop like this:
no_exit: ; preds = %entry, %no_exit
%indvar = phi uint [ 0, %entry ], [ %indvar.next, %no_exit ] ; <uint> [#uses=3]
%tmp.4 = getelementptr [1000 x int]* %Array, int 0, uint %indvar ; <int*> [#uses=2]
%tmp.7 = load int* %tmp.4 ; <int> [#uses=1]
%tmp.9 = add int %tmp.7, %X ; <int> [#uses=1]
store int %tmp.9, int* %tmp.4
*** %indvar.next = add uint %indvar, 1 ; <uint> [#uses=1]
*** %exitcond = seteq uint %indvar, 999 ; <bool> [#uses=1]
br bool %exitcond, label %return, label %no_exit
Note that indvar.next and indvar can no longer be coallesced. In machine
code terms, this patch changes this code:
.LBBtest_1: # no_exit
mov %EDX, OFFSET Array
mov %ESI, %EAX
add %ESI, DWORD PTR [%EDX + 4*%ECX]
mov %EDX, OFFSET Array
mov DWORD PTR [%EDX + 4*%ECX], %ESI
mov %EDX, %ECX
inc %EDX
cmp %ECX, 999
mov %ECX, %EDX
jne .LBBtest_1 # no_exit
into this:
.LBBtest_1: # no_exit
mov %EDX, OFFSET Array
mov %ESI, %EAX
add %ESI, DWORD PTR [%EDX + 4*%ECX]
mov %EDX, OFFSET Array
mov DWORD PTR [%EDX + 4*%ECX], %ESI
inc %ECX
cmp %ECX, 1000
jne .LBBtest_1 # no_exit
We need better instruction selection to get this:
.LBBtest_1: # no_exit
add DWORD PTR [Array + 4*%ECX], EAX
inc %ECX
cmp %ECX, 1000
jne .LBBtest_1 # no_exit
... but at least there is less register juggling
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16473 91177308-0d34-0410-b5e6-96231b3b80d8
2004-09-21 21:35:23 +00:00
|
|
|
if (BO->hasOneUse())
|
|
|
|
return new SetCondInst(I.getOpcode(), BO->getOperand(0),
|
|
|
|
ConstantExpr::getSub(CI, BOp1C));
|
2004-06-27 22:51:36 +00:00
|
|
|
} else if (CI->isNullValue()) {
|
2003-08-13 05:33:12 +00:00
|
|
|
// Replace ((add A, B) != 0) with (A != -B) if A or B is
|
|
|
|
// efficiently invertible, or if the add has just this one use.
|
|
|
|
Value *BOp0 = BO->getOperand(0), *BOp1 = BO->getOperand(1);
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2003-08-13 05:33:12 +00:00
|
|
|
if (Value *NegVal = dyn_castNegVal(BOp1))
|
|
|
|
return new SetCondInst(I.getOpcode(), BOp0, NegVal);
|
|
|
|
else if (Value *NegVal = dyn_castNegVal(BOp0))
|
|
|
|
return new SetCondInst(I.getOpcode(), NegVal, BOp1);
|
2003-10-15 16:48:29 +00:00
|
|
|
else if (BO->hasOneUse()) {
|
2003-08-13 05:33:12 +00:00
|
|
|
Instruction *Neg = BinaryOperator::createNeg(BOp1, BO->getName());
|
|
|
|
BO->setName("");
|
|
|
|
InsertNewInstBefore(Neg, I);
|
|
|
|
return new SetCondInst(I.getOpcode(), BOp0, Neg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case Instruction::Xor:
|
|
|
|
// For the xor case, we can xor two constants together, eliminating
|
|
|
|
// the explicit xor.
|
|
|
|
if (Constant *BOC = dyn_cast<Constant>(BO->getOperand(1)))
|
|
|
|
return BinaryOperator::create(I.getOpcode(), BO->getOperand(0),
|
2004-06-10 02:07:29 +00:00
|
|
|
ConstantExpr::getXor(CI, BOC));
|
2003-08-13 05:33:12 +00:00
|
|
|
|
|
|
|
// FALLTHROUGH
|
|
|
|
case Instruction::Sub:
|
|
|
|
// Replace (([sub|xor] A, B) != 0) with (A != B)
|
|
|
|
if (CI->isNullValue())
|
|
|
|
return new SetCondInst(I.getOpcode(), BO->getOperand(0),
|
|
|
|
BO->getOperand(1));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Instruction::Or:
|
|
|
|
// If bits are being or'd in that are not present in the constant we
|
|
|
|
// are comparing against, then the comparison could never succeed!
|
2004-01-12 19:35:11 +00:00
|
|
|
if (Constant *BOC = dyn_cast<Constant>(BO->getOperand(1))) {
|
2004-06-10 02:12:35 +00:00
|
|
|
Constant *NotCI = ConstantExpr::getNot(CI);
|
2004-06-10 02:07:29 +00:00
|
|
|
if (!ConstantExpr::getAnd(BOC, NotCI)->isNullValue())
|
2003-07-23 17:02:11 +00:00
|
|
|
return ReplaceInstUsesWith(I, ConstantBool::get(isSetNE));
|
2004-01-12 19:35:11 +00:00
|
|
|
}
|
2003-08-13 05:33:12 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case Instruction::And:
|
|
|
|
if (ConstantInt *BOC = dyn_cast<ConstantInt>(BO->getOperand(1))) {
|
2003-07-23 17:02:11 +00:00
|
|
|
// If bits are being compared against that are and'd out, then the
|
|
|
|
// comparison can never succeed!
|
2004-06-10 02:12:35 +00:00
|
|
|
if (!ConstantExpr::getAnd(CI,
|
|
|
|
ConstantExpr::getNot(BOC))->isNullValue())
|
2003-07-23 17:02:11 +00:00
|
|
|
return ReplaceInstUsesWith(I, ConstantBool::get(isSetNE));
|
2003-08-13 05:33:12 +00:00
|
|
|
|
2004-06-09 07:59:58 +00:00
|
|
|
// If we have ((X & C) == C), turn it into ((X & C) != 0).
|
Fix a bug in my checkin from last night that caused miscompilations of
186.crafty, fhourstones and 132.ijpeg.
Bugpoint makes really nasty miscompilations embarassingly easy to find. It
narrowed it down to the instcombiner and this testcase (from fhourstones):
bool %l7153_l4706_htstat_loopentry_2E_4_no_exit_2E_4(int* %i, [32 x int]* %works, int* %tmp.98.out) {
newFuncRoot:
%tmp.96 = load int* %i ; <int> [#uses=1]
%tmp.97 = getelementptr [32 x int]* %works, long 0, int %tmp.96 ; <int*> [#uses=1]
%tmp.98 = load int* %tmp.97 ; <int> [#uses=2]
%tmp.99 = load int* %i ; <int> [#uses=1]
%tmp.100 = and int %tmp.99, 7 ; <int> [#uses=1]
%tmp.101 = seteq int %tmp.100, 7 ; <bool> [#uses=2]
%tmp.102 = cast bool %tmp.101 to int ; <int> [#uses=0]
br bool %tmp.101, label %codeRepl4.exitStub, label %codeRepl3.exitStub
codeRepl4.exitStub: ; preds = %newFuncRoot
store int %tmp.98, int* %tmp.98.out
ret bool true
codeRepl3.exitStub: ; preds = %newFuncRoot
store int %tmp.98, int* %tmp.98.out
ret bool false
}
... which only has one combination performed on it:
$ llvm-as < t.ll | opt -instcombine -debug | llvm-dis
IC: Old = %tmp.101 = seteq int %tmp.100, 7 ; <bool> [#uses=1]
New = setne int %tmp.100, 0 ; <bool>:<badref> [#uses=0]
IC: MOD = br bool %tmp.101, label %codeRepl3.exitStub, label %codeRepl4.exitStub
IC: MOD = %tmp.97 = getelementptr [32 x int]* %works, uint 0, int %tmp.96 ; <int*> [#uses=1]
It doesn't get much better than this. :)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@14109 91177308-0d34-0410-b5e6-96231b3b80d8
2004-06-10 02:33:20 +00:00
|
|
|
if (CI == BOC && isOneBitSet(CI))
|
2004-06-09 07:59:58 +00:00
|
|
|
return new SetCondInst(isSetNE ? Instruction::SetEQ :
|
|
|
|
Instruction::SetNE, Op0,
|
|
|
|
Constant::getNullValue(CI->getType()));
|
|
|
|
|
2003-08-13 05:33:12 +00:00
|
|
|
// Replace (and X, (1 << size(X)-1) != 0) with x < 0, converting X
|
|
|
|
// to be a signed value as appropriate.
|
|
|
|
if (isSignBit(BOC)) {
|
|
|
|
Value *X = BO->getOperand(0);
|
|
|
|
// If 'X' is not signed, insert a cast now...
|
|
|
|
if (!BOC->getType()->isSigned()) {
|
2004-06-17 18:16:02 +00:00
|
|
|
const Type *DestTy = BOC->getType()->getSignedVersion();
|
2004-09-27 19:29:18 +00:00
|
|
|
X = InsertCastBefore(X, DestTy, I);
|
2003-08-13 05:33:12 +00:00
|
|
|
}
|
|
|
|
return new SetCondInst(isSetNE ? Instruction::SetLT :
|
|
|
|
Instruction::SetGE, X,
|
|
|
|
Constant::getNullValue(X->getType()));
|
|
|
|
}
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2004-09-27 19:29:18 +00:00
|
|
|
// ((X & ~7) == 0) --> X < 8
|
2004-09-23 21:46:38 +00:00
|
|
|
if (CI->isNullValue() && isHighOnes(BOC)) {
|
|
|
|
Value *X = BO->getOperand(0);
|
2004-09-27 19:29:18 +00:00
|
|
|
Constant *NegX = ConstantExpr::getNeg(BOC);
|
2004-09-23 21:46:38 +00:00
|
|
|
|
|
|
|
// If 'X' is signed, insert a cast now.
|
2004-09-27 19:29:18 +00:00
|
|
|
if (NegX->getType()->isSigned()) {
|
|
|
|
const Type *DestTy = NegX->getType()->getUnsignedVersion();
|
|
|
|
X = InsertCastBefore(X, DestTy, I);
|
|
|
|
NegX = ConstantExpr::getCast(NegX, DestTy);
|
2004-09-23 21:46:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return new SetCondInst(isSetNE ? Instruction::SetGE :
|
2004-09-27 19:29:18 +00:00
|
|
|
Instruction::SetLT, X, NegX);
|
2004-09-23 21:46:38 +00:00
|
|
|
}
|
|
|
|
|
2003-07-23 17:02:11 +00:00
|
|
|
}
|
2003-08-13 05:33:12 +00:00
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
}
|
2004-02-23 07:16:20 +00:00
|
|
|
} else { // Not a SetEQ/SetNE
|
2005-04-21 23:48:37 +00:00
|
|
|
// If the LHS is a cast from an integral value of the same size,
|
2004-02-23 07:16:20 +00:00
|
|
|
if (CastInst *Cast = dyn_cast<CastInst>(Op0)) {
|
|
|
|
Value *CastOp = Cast->getOperand(0);
|
|
|
|
const Type *SrcTy = CastOp->getType();
|
2005-04-24 06:59:08 +00:00
|
|
|
unsigned SrcTySize = SrcTy->getPrimitiveSizeInBits();
|
2004-02-23 07:16:20 +00:00
|
|
|
if (SrcTy != Cast->getType() && SrcTy->isInteger() &&
|
2005-04-24 06:59:08 +00:00
|
|
|
SrcTySize == Cast->getType()->getPrimitiveSizeInBits()) {
|
2005-04-21 23:48:37 +00:00
|
|
|
assert((SrcTy->isSigned() ^ Cast->getType()->isSigned()) &&
|
2004-02-23 07:16:20 +00:00
|
|
|
"Source and destination signednesses should differ!");
|
|
|
|
if (Cast->getType()->isSigned()) {
|
|
|
|
// If this is a signed comparison, check for comparisons in the
|
|
|
|
// vicinity of zero.
|
|
|
|
if (I.getOpcode() == Instruction::SetLT && CI->isNullValue())
|
|
|
|
// X < 0 => x > 127
|
2004-06-10 02:07:29 +00:00
|
|
|
return BinaryOperator::createSetGT(CastOp,
|
2005-04-24 06:59:08 +00:00
|
|
|
ConstantUInt::get(SrcTy, (1ULL << (SrcTySize-1))-1));
|
2004-02-23 07:16:20 +00:00
|
|
|
else if (I.getOpcode() == Instruction::SetGT &&
|
|
|
|
cast<ConstantSInt>(CI)->getValue() == -1)
|
|
|
|
// X > -1 => x < 128
|
2004-06-10 02:07:29 +00:00
|
|
|
return BinaryOperator::createSetLT(CastOp,
|
2005-04-24 06:59:08 +00:00
|
|
|
ConstantUInt::get(SrcTy, 1ULL << (SrcTySize-1)));
|
2004-02-23 07:16:20 +00:00
|
|
|
} else {
|
|
|
|
ConstantUInt *CUI = cast<ConstantUInt>(CI);
|
|
|
|
if (I.getOpcode() == Instruction::SetLT &&
|
2005-04-24 06:59:08 +00:00
|
|
|
CUI->getValue() == 1ULL << (SrcTySize-1))
|
2004-02-23 07:16:20 +00:00
|
|
|
// X < 128 => X > -1
|
2004-06-10 02:07:29 +00:00
|
|
|
return BinaryOperator::createSetGT(CastOp,
|
|
|
|
ConstantSInt::get(SrcTy, -1));
|
2004-02-23 07:16:20 +00:00
|
|
|
else if (I.getOpcode() == Instruction::SetGT &&
|
2005-04-24 06:59:08 +00:00
|
|
|
CUI->getValue() == (1ULL << (SrcTySize-1))-1)
|
2004-02-23 07:16:20 +00:00
|
|
|
// X > 127 => X < 0
|
2004-06-10 02:07:29 +00:00
|
|
|
return BinaryOperator::createSetLT(CastOp,
|
|
|
|
Constant::getNullValue(SrcTy));
|
2004-02-23 07:16:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2003-06-04 05:10:11 +00:00
|
|
|
}
|
2002-05-06 16:14:14 +00:00
|
|
|
}
|
|
|
|
|
2005-04-23 15:31:55 +00:00
|
|
|
// Handle setcc with constant RHS's that can be integer, FP or pointer.
|
|
|
|
if (Constant *RHSC = dyn_cast<Constant>(Op1)) {
|
|
|
|
if (Instruction *LHSI = dyn_cast<Instruction>(Op0))
|
|
|
|
switch (LHSI->getOpcode()) {
|
2005-05-01 04:42:15 +00:00
|
|
|
case Instruction::GetElementPtr:
|
|
|
|
if (RHSC->isNullValue()) {
|
|
|
|
// Transform setcc GEP P, int 0, int 0, int 0, null -> setcc P, null
|
|
|
|
bool isAllZeros = true;
|
|
|
|
for (unsigned i = 1, e = LHSI->getNumOperands(); i != e; ++i)
|
|
|
|
if (!isa<Constant>(LHSI->getOperand(i)) ||
|
|
|
|
!cast<Constant>(LHSI->getOperand(i))->isNullValue()) {
|
|
|
|
isAllZeros = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (isAllZeros)
|
|
|
|
return new SetCondInst(I.getOpcode(), LHSI->getOperand(0),
|
|
|
|
Constant::getNullValue(LHSI->getOperand(0)->getType()));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2005-04-23 15:31:55 +00:00
|
|
|
case Instruction::PHI:
|
|
|
|
if (Instruction *NV = FoldOpIntoPhi(I))
|
|
|
|
return NV;
|
|
|
|
break;
|
|
|
|
case Instruction::Select:
|
|
|
|
// If either operand of the select is a constant, we can fold the
|
|
|
|
// comparison into the select arms, which will cause one to be
|
|
|
|
// constant folded and the select turned into a bitwise or.
|
|
|
|
Value *Op1 = 0, *Op2 = 0;
|
|
|
|
if (LHSI->hasOneUse()) {
|
|
|
|
if (Constant *C = dyn_cast<Constant>(LHSI->getOperand(1))) {
|
|
|
|
// Fold the known value into the constant operand.
|
|
|
|
Op1 = ConstantExpr::get(I.getOpcode(), C, RHSC);
|
|
|
|
// Insert a new SetCC of the other select operand.
|
|
|
|
Op2 = InsertNewInstBefore(new SetCondInst(I.getOpcode(),
|
|
|
|
LHSI->getOperand(2), RHSC,
|
|
|
|
I.getName()), I);
|
|
|
|
} else if (Constant *C = dyn_cast<Constant>(LHSI->getOperand(2))) {
|
|
|
|
// Fold the known value into the constant operand.
|
|
|
|
Op2 = ConstantExpr::get(I.getOpcode(), C, RHSC);
|
|
|
|
// Insert a new SetCC of the other select operand.
|
|
|
|
Op1 = InsertNewInstBefore(new SetCondInst(I.getOpcode(),
|
|
|
|
LHSI->getOperand(1), RHSC,
|
|
|
|
I.getName()), I);
|
|
|
|
}
|
|
|
|
}
|
2005-04-23 21:38:35 +00:00
|
|
|
|
2005-04-23 15:31:55 +00:00
|
|
|
if (Op1)
|
|
|
|
return new SelectInst(LHSI->getOperand(0), Op1, Op2);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-01-13 20:14:25 +00:00
|
|
|
// If we can optimize a 'setcc GEP, P' or 'setcc P, GEP', do so now.
|
|
|
|
if (User *GEP = dyn_castGetElementPtr(Op0))
|
|
|
|
if (Instruction *NI = FoldGEPSetCC(GEP, Op1, I.getOpcode(), I))
|
|
|
|
return NI;
|
|
|
|
if (User *GEP = dyn_castGetElementPtr(Op1))
|
|
|
|
if (Instruction *NI = FoldGEPSetCC(GEP, Op0,
|
|
|
|
SetCondInst::getSwappedCondition(I.getOpcode()), I))
|
|
|
|
return NI;
|
|
|
|
|
2003-11-03 04:25:02 +00:00
|
|
|
// Test to see if the operands of the setcc are casted versions of other
|
|
|
|
// values. If the cast can be stripped off both arguments, we do so now.
|
2003-11-03 05:17:03 +00:00
|
|
|
if (CastInst *CI = dyn_cast<CastInst>(Op0)) {
|
|
|
|
Value *CastOp0 = CI->getOperand(0);
|
|
|
|
if (CastOp0->getType()->isLosslesslyConvertibleTo(CI->getType()) &&
|
2004-03-13 23:54:27 +00:00
|
|
|
(isa<Constant>(Op1) || isa<CastInst>(Op1)) &&
|
2003-11-03 04:25:02 +00:00
|
|
|
(I.getOpcode() == Instruction::SetEQ ||
|
|
|
|
I.getOpcode() == Instruction::SetNE)) {
|
|
|
|
// We keep moving the cast from the left operand over to the right
|
|
|
|
// operand, where it can often be eliminated completely.
|
2003-11-03 05:17:03 +00:00
|
|
|
Op0 = CastOp0;
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2003-11-03 04:25:02 +00:00
|
|
|
// If operand #1 is a cast instruction, see if we can eliminate it as
|
|
|
|
// well.
|
2003-11-03 05:17:03 +00:00
|
|
|
if (CastInst *CI2 = dyn_cast<CastInst>(Op1))
|
|
|
|
if (CI2->getOperand(0)->getType()->isLosslesslyConvertibleTo(
|
2003-11-03 04:25:02 +00:00
|
|
|
Op0->getType()))
|
2003-11-03 05:17:03 +00:00
|
|
|
Op1 = CI2->getOperand(0);
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2003-11-03 04:25:02 +00:00
|
|
|
// If Op1 is a constant, we can fold the cast into the constant.
|
|
|
|
if (Op1->getType() != Op0->getType())
|
|
|
|
if (Constant *Op1C = dyn_cast<Constant>(Op1)) {
|
|
|
|
Op1 = ConstantExpr::getCast(Op1C, Op0->getType());
|
|
|
|
} else {
|
|
|
|
// Otherwise, cast the RHS right before the setcc
|
|
|
|
Op1 = new CastInst(Op1, Op0->getType(), Op1->getName());
|
|
|
|
InsertNewInstBefore(cast<Instruction>(Op1), I);
|
|
|
|
}
|
|
|
|
return BinaryOperator::create(I.getOpcode(), Op0, Op1);
|
|
|
|
}
|
|
|
|
|
2003-11-03 05:17:03 +00:00
|
|
|
// Handle the special case of: setcc (cast bool to X), <cst>
|
|
|
|
// This comes up when you have code like
|
|
|
|
// int X = A < B;
|
|
|
|
// if (X) ...
|
|
|
|
// For generality, we handle any zero-extension of any operand comparison
|
2005-04-24 06:59:08 +00:00
|
|
|
// with a constant or another cast from the same type.
|
|
|
|
if (isa<ConstantInt>(Op1) || isa<CastInst>(Op1))
|
|
|
|
if (Instruction *R = visitSetCondInstWithCastAndCast(I))
|
|
|
|
return R;
|
2003-11-03 05:17:03 +00:00
|
|
|
}
|
2006-02-27 01:44:11 +00:00
|
|
|
|
|
|
|
if (I.getOpcode() == Instruction::SetNE ||
|
|
|
|
I.getOpcode() == Instruction::SetEQ) {
|
|
|
|
Value *A, *B;
|
|
|
|
if (match(Op0, m_Xor(m_Value(A), m_Value(B))) &&
|
|
|
|
(A == Op1 || B == Op1)) {
|
|
|
|
// (A^B) == A -> B == 0
|
|
|
|
Value *OtherVal = A == Op1 ? B : A;
|
|
|
|
return BinaryOperator::create(I.getOpcode(), OtherVal,
|
|
|
|
Constant::getNullValue(A->getType()));
|
|
|
|
} else if (match(Op1, m_Xor(m_Value(A), m_Value(B))) &&
|
|
|
|
(A == Op0 || B == Op0)) {
|
|
|
|
// A == (A^B) -> B == 0
|
|
|
|
Value *OtherVal = A == Op0 ? B : A;
|
|
|
|
return BinaryOperator::create(I.getOpcode(), OtherVal,
|
|
|
|
Constant::getNullValue(A->getType()));
|
|
|
|
} else if (match(Op0, m_Sub(m_Value(A), m_Value(B))) && A == Op1) {
|
|
|
|
// (A-B) == A -> B == 0
|
|
|
|
return BinaryOperator::create(I.getOpcode(), B,
|
|
|
|
Constant::getNullValue(B->getType()));
|
|
|
|
} else if (match(Op1, m_Sub(m_Value(A), m_Value(B))) && A == Op0) {
|
|
|
|
// A == (A-B) -> B == 0
|
|
|
|
return BinaryOperator::create(I.getOpcode(), B,
|
|
|
|
Constant::getNullValue(B->getType()));
|
|
|
|
}
|
|
|
|
}
|
2002-06-25 16:13:24 +00:00
|
|
|
return Changed ? &I : 0;
|
2002-05-06 16:14:14 +00:00
|
|
|
}
|
|
|
|
|
2005-04-24 06:59:08 +00:00
|
|
|
// visitSetCondInstWithCastAndCast - Handle setcond (cast x to y), (cast/cst).
|
|
|
|
// We only handle extending casts so far.
|
|
|
|
//
|
|
|
|
Instruction *InstCombiner::visitSetCondInstWithCastAndCast(SetCondInst &SCI) {
|
|
|
|
Value *LHSCIOp = cast<CastInst>(SCI.getOperand(0))->getOperand(0);
|
|
|
|
const Type *SrcTy = LHSCIOp->getType();
|
|
|
|
const Type *DestTy = SCI.getOperand(0)->getType();
|
|
|
|
Value *RHSCIOp;
|
|
|
|
|
|
|
|
if (!DestTy->isIntegral() || !SrcTy->isIntegral())
|
2005-01-17 03:20:02 +00:00
|
|
|
return 0;
|
|
|
|
|
2005-04-24 06:59:08 +00:00
|
|
|
unsigned SrcBits = SrcTy->getPrimitiveSizeInBits();
|
|
|
|
unsigned DestBits = DestTy->getPrimitiveSizeInBits();
|
|
|
|
if (SrcBits >= DestBits) return 0; // Only handle extending cast.
|
|
|
|
|
|
|
|
// Is this a sign or zero extension?
|
|
|
|
bool isSignSrc = SrcTy->isSigned();
|
|
|
|
bool isSignDest = DestTy->isSigned();
|
|
|
|
|
|
|
|
if (CastInst *CI = dyn_cast<CastInst>(SCI.getOperand(1))) {
|
|
|
|
// Not an extension from the same type?
|
|
|
|
RHSCIOp = CI->getOperand(0);
|
|
|
|
if (RHSCIOp->getType() != LHSCIOp->getType()) return 0;
|
|
|
|
} else if (ConstantInt *CI = dyn_cast<ConstantInt>(SCI.getOperand(1))) {
|
|
|
|
// Compute the constant that would happen if we truncated to SrcTy then
|
|
|
|
// reextended to DestTy.
|
|
|
|
Constant *Res = ConstantExpr::getCast(CI, SrcTy);
|
|
|
|
|
|
|
|
if (ConstantExpr::getCast(Res, DestTy) == CI) {
|
|
|
|
RHSCIOp = Res;
|
|
|
|
} else {
|
|
|
|
// If the value cannot be represented in the shorter type, we cannot emit
|
|
|
|
// a simple comparison.
|
|
|
|
if (SCI.getOpcode() == Instruction::SetEQ)
|
|
|
|
return ReplaceInstUsesWith(SCI, ConstantBool::False);
|
|
|
|
if (SCI.getOpcode() == Instruction::SetNE)
|
|
|
|
return ReplaceInstUsesWith(SCI, ConstantBool::True);
|
|
|
|
|
|
|
|
// Evaluate the comparison for LT.
|
|
|
|
Value *Result;
|
|
|
|
if (DestTy->isSigned()) {
|
|
|
|
// We're performing a signed comparison.
|
|
|
|
if (isSignSrc) {
|
|
|
|
// Signed extend and signed comparison.
|
|
|
|
if (cast<ConstantSInt>(CI)->getValue() < 0) // X < (small) --> false
|
|
|
|
Result = ConstantBool::False;
|
|
|
|
else
|
|
|
|
Result = ConstantBool::True; // X < (large) --> true
|
|
|
|
} else {
|
|
|
|
// Unsigned extend and signed comparison.
|
|
|
|
if (cast<ConstantSInt>(CI)->getValue() < 0)
|
|
|
|
Result = ConstantBool::False;
|
|
|
|
else
|
|
|
|
Result = ConstantBool::True;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// We're performing an unsigned comparison.
|
|
|
|
if (!isSignSrc) {
|
|
|
|
// Unsigned extend & compare -> always true.
|
|
|
|
Result = ConstantBool::True;
|
|
|
|
} else {
|
|
|
|
// We're performing an unsigned comp with a sign extended value.
|
|
|
|
// This is true if the input is >= 0. [aka >s -1]
|
|
|
|
Constant *NegOne = ConstantIntegral::getAllOnesValue(SrcTy);
|
|
|
|
Result = InsertNewInstBefore(BinaryOperator::createSetGT(LHSCIOp,
|
|
|
|
NegOne, SCI.getName()), SCI);
|
|
|
|
}
|
2004-11-28 21:31:15 +00:00
|
|
|
}
|
2005-01-17 03:20:02 +00:00
|
|
|
|
2005-07-27 06:12:32 +00:00
|
|
|
// Finally, return the value computed.
|
2005-04-24 06:59:08 +00:00
|
|
|
if (SCI.getOpcode() == Instruction::SetLT) {
|
|
|
|
return ReplaceInstUsesWith(SCI, Result);
|
|
|
|
} else {
|
|
|
|
assert(SCI.getOpcode()==Instruction::SetGT &&"SetCC should be folded!");
|
|
|
|
if (Constant *CI = dyn_cast<Constant>(Result))
|
|
|
|
return ReplaceInstUsesWith(SCI, ConstantExpr::getNot(CI));
|
|
|
|
else
|
|
|
|
return BinaryOperator::createNot(Result);
|
|
|
|
}
|
2004-11-28 21:31:15 +00:00
|
|
|
}
|
2005-04-24 06:59:08 +00:00
|
|
|
} else {
|
|
|
|
return 0;
|
2004-11-28 21:31:15 +00:00
|
|
|
}
|
2002-05-06 16:14:14 +00:00
|
|
|
|
2005-06-16 03:00:08 +00:00
|
|
|
// Okay, just insert a compare of the reduced operands now!
|
2005-04-24 06:59:08 +00:00
|
|
|
return BinaryOperator::create(SCI.getOpcode(), LHSCIOp, RHSCIOp);
|
|
|
|
}
|
2002-05-06 16:14:14 +00:00
|
|
|
|
2003-03-10 19:16:08 +00:00
|
|
|
Instruction *InstCombiner::visitShiftInst(ShiftInst &I) {
|
2002-06-25 16:13:24 +00:00
|
|
|
assert(I.getOperand(1)->getType() == Type::UByteTy);
|
|
|
|
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
2003-08-12 21:53:41 +00:00
|
|
|
bool isLeftShift = I.getOpcode() == Instruction::Shl;
|
2002-05-06 16:14:14 +00:00
|
|
|
|
|
|
|
// shl X, 0 == X and shr X, 0 == X
|
|
|
|
// shl 0, X == 0 and shr 0, X == 0
|
|
|
|
if (Op1 == Constant::getNullValue(Type::UByteTy) ||
|
2002-08-12 21:17:25 +00:00
|
|
|
Op0 == Constant::getNullValue(Op0->getType()))
|
|
|
|
return ReplaceInstUsesWith(I, Op0);
|
2006-02-12 08:07:37 +00:00
|
|
|
|
2004-10-16 18:11:37 +00:00
|
|
|
if (isa<UndefValue>(Op0)) { // undef >>s X -> undef
|
|
|
|
if (!isLeftShift && I.getType()->isSigned())
|
2004-10-16 23:28:04 +00:00
|
|
|
return ReplaceInstUsesWith(I, Op0);
|
2004-10-16 18:11:37 +00:00
|
|
|
else // undef << X -> 0 AND undef >>u X -> 0
|
|
|
|
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
|
|
|
|
}
|
|
|
|
if (isa<UndefValue>(Op1)) {
|
2005-07-20 18:49:28 +00:00
|
|
|
if (isLeftShift || I.getType()->isUnsigned())// X << undef, X >>u undef -> 0
|
2004-10-16 18:11:37 +00:00
|
|
|
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
|
|
|
|
else
|
|
|
|
return ReplaceInstUsesWith(I, Op0); // X >>s undef -> X
|
|
|
|
}
|
|
|
|
|
2003-08-12 21:53:41 +00:00
|
|
|
// shr int -1, X = -1 (for any arithmetic shift rights of ~0)
|
|
|
|
if (!isLeftShift)
|
|
|
|
if (ConstantSInt *CSI = dyn_cast<ConstantSInt>(Op0))
|
|
|
|
if (CSI->isAllOnesValue())
|
|
|
|
return ReplaceInstUsesWith(I, CSI);
|
|
|
|
|
2004-04-09 19:05:30 +00:00
|
|
|
// Try to fold constant and into select arguments.
|
|
|
|
if (isa<Constant>(Op0))
|
|
|
|
if (SelectInst *SI = dyn_cast<SelectInst>(Op1))
|
2005-01-01 16:22:27 +00:00
|
|
|
if (Instruction *R = FoldOpIntoSelect(I, SI, this))
|
2004-04-09 19:05:30 +00:00
|
|
|
return R;
|
|
|
|
|
2005-05-08 17:34:56 +00:00
|
|
|
// See if we can turn a signed shr into an unsigned shr.
|
|
|
|
if (!isLeftShift && I.getType()->isSigned()) {
|
2006-02-07 07:27:52 +00:00
|
|
|
if (MaskedValueIsZero(Op0,
|
|
|
|
1ULL << (I.getType()->getPrimitiveSizeInBits()-1))) {
|
2005-05-08 17:34:56 +00:00
|
|
|
Value *V = InsertCastBefore(Op0, I.getType()->getUnsignedVersion(), I);
|
|
|
|
V = InsertNewInstBefore(new ShiftInst(Instruction::Shr, V, Op1,
|
|
|
|
I.getName()), I);
|
|
|
|
return new CastInst(V, I.getType());
|
|
|
|
}
|
|
|
|
}
|
2005-07-27 06:12:32 +00:00
|
|
|
|
2006-01-06 07:12:35 +00:00
|
|
|
if (ConstantUInt *CUI = dyn_cast<ConstantUInt>(Op1))
|
|
|
|
if (Instruction *Res = FoldShiftByConstant(Op0, CUI, I))
|
|
|
|
return Res;
|
|
|
|
return 0;
|
|
|
|
}
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2006-01-06 07:12:35 +00:00
|
|
|
Instruction *InstCombiner::FoldShiftByConstant(Value *Op0, ConstantUInt *Op1,
|
|
|
|
ShiftInst &I) {
|
|
|
|
bool isLeftShift = I.getOpcode() == Instruction::Shl;
|
2006-01-06 07:22:22 +00:00
|
|
|
bool isSignedShift = Op0->getType()->isSigned();
|
|
|
|
bool isUnsignedShift = !isSignedShift;
|
2003-08-13 04:18:28 +00:00
|
|
|
|
2006-02-12 08:07:37 +00:00
|
|
|
// See if we can simplify any instructions used by the instruction whose sole
|
|
|
|
// purpose is to compute bits we don't care about.
|
|
|
|
uint64_t KnownZero, KnownOne;
|
|
|
|
if (SimplifyDemandedBits(&I, I.getType()->getIntegralTypeMask(),
|
|
|
|
KnownZero, KnownOne))
|
|
|
|
return &I;
|
|
|
|
|
2006-01-06 07:12:35 +00:00
|
|
|
// shl uint X, 32 = 0 and shr ubyte Y, 9 = 0, ... just don't eliminate shr
|
|
|
|
// of a signed value.
|
|
|
|
//
|
|
|
|
unsigned TypeBits = Op0->getType()->getPrimitiveSizeInBits();
|
|
|
|
if (Op1->getValue() >= TypeBits) {
|
2006-01-06 07:22:22 +00:00
|
|
|
if (isUnsignedShift || isLeftShift)
|
2006-01-06 07:12:35 +00:00
|
|
|
return ReplaceInstUsesWith(I, Constant::getNullValue(Op0->getType()));
|
|
|
|
else {
|
|
|
|
I.setOperand(1, ConstantUInt::get(Type::UByteTy, TypeBits-1));
|
|
|
|
return &I;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ((X*C1) << C2) == (X * (C1 << C2))
|
|
|
|
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(Op0))
|
|
|
|
if (BO->getOpcode() == Instruction::Mul && isLeftShift)
|
|
|
|
if (Constant *BOOp = dyn_cast<Constant>(BO->getOperand(1)))
|
|
|
|
return BinaryOperator::createMul(BO->getOperand(0),
|
|
|
|
ConstantExpr::getShl(BOOp, Op1));
|
|
|
|
|
|
|
|
// Try to fold constant and into select arguments.
|
|
|
|
if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
|
|
|
|
if (Instruction *R = FoldOpIntoSelect(I, SI, this))
|
|
|
|
return R;
|
|
|
|
if (isa<PHINode>(Op0))
|
|
|
|
if (Instruction *NV = FoldOpIntoPhi(I))
|
|
|
|
return NV;
|
|
|
|
|
|
|
|
if (Op0->hasOneUse()) {
|
|
|
|
if (BinaryOperator *Op0BO = dyn_cast<BinaryOperator>(Op0)) {
|
|
|
|
// Turn ((X >> C) + Y) << C -> (X + (Y << C)) & (~0 << C)
|
|
|
|
Value *V1, *V2;
|
|
|
|
ConstantInt *CC;
|
|
|
|
switch (Op0BO->getOpcode()) {
|
implement shift.ll:test25. This compiles:
struct S { unsigned int i : 6, j : 11, k : 15; } b;
void plus3 (unsigned int x) {
b.k += x;
}
to:
_plus3:
lis r2, ha16(L_b$non_lazy_ptr)
lwz r2, lo16(L_b$non_lazy_ptr)(r2)
lwz r3, 0(r2)
rlwinm r4, r3, 0, 0, 14
add r4, r4, r3
rlwimi r4, r3, 0, 15, 31
stw r4, 0(r2)
blr
instead of:
_plus3:
lis r2, ha16(L_b$non_lazy_ptr)
lwz r2, lo16(L_b$non_lazy_ptr)(r2)
lwz r4, 0(r2)
srwi r5, r4, 17
add r3, r5, r3
slwi r3, r3, 17
rlwimi r3, r4, 0, 15, 31
stw r3, 0(r2)
blr
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23381 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-18 05:12:10 +00:00
|
|
|
default: break;
|
|
|
|
case Instruction::Add:
|
|
|
|
case Instruction::And:
|
|
|
|
case Instruction::Or:
|
|
|
|
case Instruction::Xor:
|
|
|
|
// These operators commute.
|
|
|
|
// Turn (Y + (X >> C)) << C -> (X + (Y << C)) & (~0 << C)
|
Compile
struct S { unsigned int i : 6, j : 11, k : 15; } b;
void plus2 (unsigned int x) {
b.j += x;
}
to:
plus2:
mov %EAX, DWORD PTR [b]
mov %ECX, %EAX
and %ECX, 131008
mov %EDX, DWORD PTR [%ESP + 4]
shl %EDX, 6
add %EDX, %ECX
and %EDX, 131008
and %EAX, -131009
or %EDX, %EAX
mov DWORD PTR [b], %EDX
ret
instead of:
plus2:
mov %EAX, DWORD PTR [b]
mov %ECX, %EAX
shr %ECX, 6
and %ECX, 2047
add %ECX, DWORD PTR [%ESP + 4]
shl %ECX, 6
and %ECX, 131008
and %EAX, -131009
or %ECX, %EAX
mov DWORD PTR [b], %ECX
ret
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23385 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-18 06:30:59 +00:00
|
|
|
if (isLeftShift && Op0BO->getOperand(1)->hasOneUse() &&
|
|
|
|
match(Op0BO->getOperand(1),
|
2006-01-06 07:12:35 +00:00
|
|
|
m_Shr(m_Value(V1), m_ConstantInt(CC))) && CC == Op1) {
|
Compile
struct S { unsigned int i : 6, j : 11, k : 15; } b;
void plus2 (unsigned int x) {
b.j += x;
}
to:
plus2:
mov %EAX, DWORD PTR [b]
mov %ECX, %EAX
and %ECX, 131008
mov %EDX, DWORD PTR [%ESP + 4]
shl %EDX, 6
add %EDX, %ECX
and %EDX, 131008
and %EAX, -131009
or %EDX, %EAX
mov DWORD PTR [b], %EDX
ret
instead of:
plus2:
mov %EAX, DWORD PTR [b]
mov %ECX, %EAX
shr %ECX, 6
and %ECX, 2047
add %ECX, DWORD PTR [%ESP + 4]
shl %ECX, 6
and %ECX, 131008
and %EAX, -131009
or %ECX, %EAX
mov DWORD PTR [b], %ECX
ret
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23385 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-18 06:30:59 +00:00
|
|
|
Instruction *YS = new ShiftInst(Instruction::Shl,
|
2006-01-06 07:12:35 +00:00
|
|
|
Op0BO->getOperand(0), Op1,
|
Compile
struct S { unsigned int i : 6, j : 11, k : 15; } b;
void plus2 (unsigned int x) {
b.j += x;
}
to:
plus2:
mov %EAX, DWORD PTR [b]
mov %ECX, %EAX
and %ECX, 131008
mov %EDX, DWORD PTR [%ESP + 4]
shl %EDX, 6
add %EDX, %ECX
and %EDX, 131008
and %EAX, -131009
or %EDX, %EAX
mov DWORD PTR [b], %EDX
ret
instead of:
plus2:
mov %EAX, DWORD PTR [b]
mov %ECX, %EAX
shr %ECX, 6
and %ECX, 2047
add %ECX, DWORD PTR [%ESP + 4]
shl %ECX, 6
and %ECX, 131008
and %EAX, -131009
or %ECX, %EAX
mov DWORD PTR [b], %ECX
ret
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23385 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-18 06:30:59 +00:00
|
|
|
Op0BO->getName());
|
|
|
|
InsertNewInstBefore(YS, I); // (Y << C)
|
2006-02-09 07:41:14 +00:00
|
|
|
Instruction *X =
|
|
|
|
BinaryOperator::create(Op0BO->getOpcode(), YS, V1,
|
|
|
|
Op0BO->getOperand(1)->getName());
|
Compile
struct S { unsigned int i : 6, j : 11, k : 15; } b;
void plus2 (unsigned int x) {
b.j += x;
}
to:
plus2:
mov %EAX, DWORD PTR [b]
mov %ECX, %EAX
and %ECX, 131008
mov %EDX, DWORD PTR [%ESP + 4]
shl %EDX, 6
add %EDX, %ECX
and %EDX, 131008
and %EAX, -131009
or %EDX, %EAX
mov DWORD PTR [b], %EDX
ret
instead of:
plus2:
mov %EAX, DWORD PTR [b]
mov %ECX, %EAX
shr %ECX, 6
and %ECX, 2047
add %ECX, DWORD PTR [%ESP + 4]
shl %ECX, 6
and %ECX, 131008
and %EAX, -131009
or %ECX, %EAX
mov DWORD PTR [b], %ECX
ret
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23385 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-18 06:30:59 +00:00
|
|
|
InsertNewInstBefore(X, I); // (X + (Y << C))
|
|
|
|
Constant *C2 = ConstantInt::getAllOnesValue(X->getType());
|
2006-01-06 07:12:35 +00:00
|
|
|
C2 = ConstantExpr::getShl(C2, Op1);
|
Compile
struct S { unsigned int i : 6, j : 11, k : 15; } b;
void plus2 (unsigned int x) {
b.j += x;
}
to:
plus2:
mov %EAX, DWORD PTR [b]
mov %ECX, %EAX
and %ECX, 131008
mov %EDX, DWORD PTR [%ESP + 4]
shl %EDX, 6
add %EDX, %ECX
and %EDX, 131008
and %EAX, -131009
or %EDX, %EAX
mov DWORD PTR [b], %EDX
ret
instead of:
plus2:
mov %EAX, DWORD PTR [b]
mov %ECX, %EAX
shr %ECX, 6
and %ECX, 2047
add %ECX, DWORD PTR [%ESP + 4]
shl %ECX, 6
and %ECX, 131008
and %EAX, -131009
or %ECX, %EAX
mov DWORD PTR [b], %ECX
ret
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23385 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-18 06:30:59 +00:00
|
|
|
return BinaryOperator::createAnd(X, C2);
|
|
|
|
}
|
2006-01-06 07:12:35 +00:00
|
|
|
|
Compile
struct S { unsigned int i : 6, j : 11, k : 15; } b;
void plus2 (unsigned int x) {
b.j += x;
}
to:
plus2:
mov %EAX, DWORD PTR [b]
mov %ECX, %EAX
and %ECX, 131008
mov %EDX, DWORD PTR [%ESP + 4]
shl %EDX, 6
add %EDX, %ECX
and %EDX, 131008
and %EAX, -131009
or %EDX, %EAX
mov DWORD PTR [b], %EDX
ret
instead of:
plus2:
mov %EAX, DWORD PTR [b]
mov %ECX, %EAX
shr %ECX, 6
and %ECX, 2047
add %ECX, DWORD PTR [%ESP + 4]
shl %ECX, 6
and %ECX, 131008
and %EAX, -131009
or %ECX, %EAX
mov DWORD PTR [b], %ECX
ret
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23385 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-18 06:30:59 +00:00
|
|
|
// Turn (Y + ((X >> C) & CC)) << C -> ((X & (CC << C)) + (Y << C))
|
|
|
|
if (isLeftShift && Op0BO->getOperand(1)->hasOneUse() &&
|
|
|
|
match(Op0BO->getOperand(1),
|
|
|
|
m_And(m_Shr(m_Value(V1), m_Value(V2)),
|
2006-01-06 07:12:35 +00:00
|
|
|
m_ConstantInt(CC))) && V2 == Op1 &&
|
2006-02-09 07:41:14 +00:00
|
|
|
cast<BinaryOperator>(Op0BO->getOperand(1))->getOperand(0)->hasOneUse()) {
|
Compile
struct S { unsigned int i : 6, j : 11, k : 15; } b;
void plus2 (unsigned int x) {
b.j += x;
}
to:
plus2:
mov %EAX, DWORD PTR [b]
mov %ECX, %EAX
and %ECX, 131008
mov %EDX, DWORD PTR [%ESP + 4]
shl %EDX, 6
add %EDX, %ECX
and %EDX, 131008
and %EAX, -131009
or %EDX, %EAX
mov DWORD PTR [b], %EDX
ret
instead of:
plus2:
mov %EAX, DWORD PTR [b]
mov %ECX, %EAX
shr %ECX, 6
and %ECX, 2047
add %ECX, DWORD PTR [%ESP + 4]
shl %ECX, 6
and %ECX, 131008
and %EAX, -131009
or %ECX, %EAX
mov DWORD PTR [b], %ECX
ret
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23385 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-18 06:30:59 +00:00
|
|
|
Instruction *YS = new ShiftInst(Instruction::Shl,
|
2006-01-06 07:12:35 +00:00
|
|
|
Op0BO->getOperand(0), Op1,
|
Compile
struct S { unsigned int i : 6, j : 11, k : 15; } b;
void plus2 (unsigned int x) {
b.j += x;
}
to:
plus2:
mov %EAX, DWORD PTR [b]
mov %ECX, %EAX
and %ECX, 131008
mov %EDX, DWORD PTR [%ESP + 4]
shl %EDX, 6
add %EDX, %ECX
and %EDX, 131008
and %EAX, -131009
or %EDX, %EAX
mov DWORD PTR [b], %EDX
ret
instead of:
plus2:
mov %EAX, DWORD PTR [b]
mov %ECX, %EAX
shr %ECX, 6
and %ECX, 2047
add %ECX, DWORD PTR [%ESP + 4]
shl %ECX, 6
and %ECX, 131008
and %EAX, -131009
or %ECX, %EAX
mov DWORD PTR [b], %ECX
ret
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23385 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-18 06:30:59 +00:00
|
|
|
Op0BO->getName());
|
|
|
|
InsertNewInstBefore(YS, I); // (Y << C)
|
|
|
|
Instruction *XM =
|
2006-01-06 07:12:35 +00:00
|
|
|
BinaryOperator::createAnd(V1, ConstantExpr::getShl(CC, Op1),
|
Compile
struct S { unsigned int i : 6, j : 11, k : 15; } b;
void plus2 (unsigned int x) {
b.j += x;
}
to:
plus2:
mov %EAX, DWORD PTR [b]
mov %ECX, %EAX
and %ECX, 131008
mov %EDX, DWORD PTR [%ESP + 4]
shl %EDX, 6
add %EDX, %ECX
and %EDX, 131008
and %EAX, -131009
or %EDX, %EAX
mov DWORD PTR [b], %EDX
ret
instead of:
plus2:
mov %EAX, DWORD PTR [b]
mov %ECX, %EAX
shr %ECX, 6
and %ECX, 2047
add %ECX, DWORD PTR [%ESP + 4]
shl %ECX, 6
and %ECX, 131008
and %EAX, -131009
or %ECX, %EAX
mov DWORD PTR [b], %ECX
ret
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23385 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-18 06:30:59 +00:00
|
|
|
V1->getName()+".mask");
|
|
|
|
InsertNewInstBefore(XM, I); // X & (CC << C)
|
|
|
|
|
|
|
|
return BinaryOperator::create(Op0BO->getOpcode(), YS, XM);
|
|
|
|
}
|
2006-01-06 07:12:35 +00:00
|
|
|
|
Compile
struct S { unsigned int i : 6, j : 11, k : 15; } b;
void plus2 (unsigned int x) {
b.j += x;
}
to:
plus2:
mov %EAX, DWORD PTR [b]
mov %ECX, %EAX
and %ECX, 131008
mov %EDX, DWORD PTR [%ESP + 4]
shl %EDX, 6
add %EDX, %ECX
and %EDX, 131008
and %EAX, -131009
or %EDX, %EAX
mov DWORD PTR [b], %EDX
ret
instead of:
plus2:
mov %EAX, DWORD PTR [b]
mov %ECX, %EAX
shr %ECX, 6
and %ECX, 2047
add %ECX, DWORD PTR [%ESP + 4]
shl %ECX, 6
and %ECX, 131008
and %EAX, -131009
or %ECX, %EAX
mov DWORD PTR [b], %ECX
ret
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23385 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-18 06:30:59 +00:00
|
|
|
// FALL THROUGH.
|
implement shift.ll:test25. This compiles:
struct S { unsigned int i : 6, j : 11, k : 15; } b;
void plus3 (unsigned int x) {
b.k += x;
}
to:
_plus3:
lis r2, ha16(L_b$non_lazy_ptr)
lwz r2, lo16(L_b$non_lazy_ptr)(r2)
lwz r3, 0(r2)
rlwinm r4, r3, 0, 0, 14
add r4, r4, r3
rlwimi r4, r3, 0, 15, 31
stw r4, 0(r2)
blr
instead of:
_plus3:
lis r2, ha16(L_b$non_lazy_ptr)
lwz r2, lo16(L_b$non_lazy_ptr)(r2)
lwz r4, 0(r2)
srwi r5, r4, 17
add r3, r5, r3
slwi r3, r3, 17
rlwimi r3, r4, 0, 15, 31
stw r3, 0(r2)
blr
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23381 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-18 05:12:10 +00:00
|
|
|
case Instruction::Sub:
|
|
|
|
// Turn ((X >> C) + Y) << C -> (X + (Y << C)) & (~0 << C)
|
Compile
struct S { unsigned int i : 6, j : 11, k : 15; } b;
void plus2 (unsigned int x) {
b.j += x;
}
to:
plus2:
mov %EAX, DWORD PTR [b]
mov %ECX, %EAX
and %ECX, 131008
mov %EDX, DWORD PTR [%ESP + 4]
shl %EDX, 6
add %EDX, %ECX
and %EDX, 131008
and %EAX, -131009
or %EDX, %EAX
mov DWORD PTR [b], %EDX
ret
instead of:
plus2:
mov %EAX, DWORD PTR [b]
mov %ECX, %EAX
shr %ECX, 6
and %ECX, 2047
add %ECX, DWORD PTR [%ESP + 4]
shl %ECX, 6
and %ECX, 131008
and %EAX, -131009
or %ECX, %EAX
mov DWORD PTR [b], %ECX
ret
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23385 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-18 06:30:59 +00:00
|
|
|
if (isLeftShift && Op0BO->getOperand(0)->hasOneUse() &&
|
|
|
|
match(Op0BO->getOperand(0),
|
2006-01-06 07:12:35 +00:00
|
|
|
m_Shr(m_Value(V1), m_ConstantInt(CC))) && CC == Op1) {
|
Compile
struct S { unsigned int i : 6, j : 11, k : 15; } b;
void plus2 (unsigned int x) {
b.j += x;
}
to:
plus2:
mov %EAX, DWORD PTR [b]
mov %ECX, %EAX
and %ECX, 131008
mov %EDX, DWORD PTR [%ESP + 4]
shl %EDX, 6
add %EDX, %ECX
and %EDX, 131008
and %EAX, -131009
or %EDX, %EAX
mov DWORD PTR [b], %EDX
ret
instead of:
plus2:
mov %EAX, DWORD PTR [b]
mov %ECX, %EAX
shr %ECX, 6
and %ECX, 2047
add %ECX, DWORD PTR [%ESP + 4]
shl %ECX, 6
and %ECX, 131008
and %EAX, -131009
or %ECX, %EAX
mov DWORD PTR [b], %ECX
ret
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23385 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-18 06:30:59 +00:00
|
|
|
Instruction *YS = new ShiftInst(Instruction::Shl,
|
2006-01-06 07:12:35 +00:00
|
|
|
Op0BO->getOperand(1), Op1,
|
Compile
struct S { unsigned int i : 6, j : 11, k : 15; } b;
void plus2 (unsigned int x) {
b.j += x;
}
to:
plus2:
mov %EAX, DWORD PTR [b]
mov %ECX, %EAX
and %ECX, 131008
mov %EDX, DWORD PTR [%ESP + 4]
shl %EDX, 6
add %EDX, %ECX
and %EDX, 131008
and %EAX, -131009
or %EDX, %EAX
mov DWORD PTR [b], %EDX
ret
instead of:
plus2:
mov %EAX, DWORD PTR [b]
mov %ECX, %EAX
shr %ECX, 6
and %ECX, 2047
add %ECX, DWORD PTR [%ESP + 4]
shl %ECX, 6
and %ECX, 131008
and %EAX, -131009
or %ECX, %EAX
mov DWORD PTR [b], %ECX
ret
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23385 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-18 06:30:59 +00:00
|
|
|
Op0BO->getName());
|
|
|
|
InsertNewInstBefore(YS, I); // (Y << C)
|
2006-02-09 07:41:14 +00:00
|
|
|
Instruction *X =
|
|
|
|
BinaryOperator::create(Op0BO->getOpcode(), YS, V1,
|
|
|
|
Op0BO->getOperand(0)->getName());
|
Compile
struct S { unsigned int i : 6, j : 11, k : 15; } b;
void plus2 (unsigned int x) {
b.j += x;
}
to:
plus2:
mov %EAX, DWORD PTR [b]
mov %ECX, %EAX
and %ECX, 131008
mov %EDX, DWORD PTR [%ESP + 4]
shl %EDX, 6
add %EDX, %ECX
and %EDX, 131008
and %EAX, -131009
or %EDX, %EAX
mov DWORD PTR [b], %EDX
ret
instead of:
plus2:
mov %EAX, DWORD PTR [b]
mov %ECX, %EAX
shr %ECX, 6
and %ECX, 2047
add %ECX, DWORD PTR [%ESP + 4]
shl %ECX, 6
and %ECX, 131008
and %EAX, -131009
or %ECX, %EAX
mov DWORD PTR [b], %ECX
ret
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23385 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-18 06:30:59 +00:00
|
|
|
InsertNewInstBefore(X, I); // (X + (Y << C))
|
|
|
|
Constant *C2 = ConstantInt::getAllOnesValue(X->getType());
|
2006-01-06 07:12:35 +00:00
|
|
|
C2 = ConstantExpr::getShl(C2, Op1);
|
Compile
struct S { unsigned int i : 6, j : 11, k : 15; } b;
void plus2 (unsigned int x) {
b.j += x;
}
to:
plus2:
mov %EAX, DWORD PTR [b]
mov %ECX, %EAX
and %ECX, 131008
mov %EDX, DWORD PTR [%ESP + 4]
shl %EDX, 6
add %EDX, %ECX
and %EDX, 131008
and %EAX, -131009
or %EDX, %EAX
mov DWORD PTR [b], %EDX
ret
instead of:
plus2:
mov %EAX, DWORD PTR [b]
mov %ECX, %EAX
shr %ECX, 6
and %ECX, 2047
add %ECX, DWORD PTR [%ESP + 4]
shl %ECX, 6
and %ECX, 131008
and %EAX, -131009
or %ECX, %EAX
mov DWORD PTR [b], %ECX
ret
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23385 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-18 06:30:59 +00:00
|
|
|
return BinaryOperator::createAnd(X, C2);
|
|
|
|
}
|
2006-01-06 07:12:35 +00:00
|
|
|
|
Compile
struct S { unsigned int i : 6, j : 11, k : 15; } b;
void plus2 (unsigned int x) {
b.j += x;
}
to:
plus2:
mov %EAX, DWORD PTR [b]
mov %ECX, %EAX
and %ECX, 131008
mov %EDX, DWORD PTR [%ESP + 4]
shl %EDX, 6
add %EDX, %ECX
and %EDX, 131008
and %EAX, -131009
or %EDX, %EAX
mov DWORD PTR [b], %EDX
ret
instead of:
plus2:
mov %EAX, DWORD PTR [b]
mov %ECX, %EAX
shr %ECX, 6
and %ECX, 2047
add %ECX, DWORD PTR [%ESP + 4]
shl %ECX, 6
and %ECX, 131008
and %EAX, -131009
or %ECX, %EAX
mov DWORD PTR [b], %ECX
ret
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23385 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-18 06:30:59 +00:00
|
|
|
if (isLeftShift && Op0BO->getOperand(0)->hasOneUse() &&
|
|
|
|
match(Op0BO->getOperand(0),
|
|
|
|
m_And(m_Shr(m_Value(V1), m_Value(V2)),
|
2006-01-06 07:12:35 +00:00
|
|
|
m_ConstantInt(CC))) && V2 == Op1 &&
|
2006-02-09 07:41:14 +00:00
|
|
|
cast<BinaryOperator>(Op0BO->getOperand(0))
|
|
|
|
->getOperand(0)->hasOneUse()) {
|
Compile
struct S { unsigned int i : 6, j : 11, k : 15; } b;
void plus2 (unsigned int x) {
b.j += x;
}
to:
plus2:
mov %EAX, DWORD PTR [b]
mov %ECX, %EAX
and %ECX, 131008
mov %EDX, DWORD PTR [%ESP + 4]
shl %EDX, 6
add %EDX, %ECX
and %EDX, 131008
and %EAX, -131009
or %EDX, %EAX
mov DWORD PTR [b], %EDX
ret
instead of:
plus2:
mov %EAX, DWORD PTR [b]
mov %ECX, %EAX
shr %ECX, 6
and %ECX, 2047
add %ECX, DWORD PTR [%ESP + 4]
shl %ECX, 6
and %ECX, 131008
and %EAX, -131009
or %ECX, %EAX
mov DWORD PTR [b], %ECX
ret
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23385 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-18 06:30:59 +00:00
|
|
|
Instruction *YS = new ShiftInst(Instruction::Shl,
|
2006-01-06 07:12:35 +00:00
|
|
|
Op0BO->getOperand(1), Op1,
|
Compile
struct S { unsigned int i : 6, j : 11, k : 15; } b;
void plus2 (unsigned int x) {
b.j += x;
}
to:
plus2:
mov %EAX, DWORD PTR [b]
mov %ECX, %EAX
and %ECX, 131008
mov %EDX, DWORD PTR [%ESP + 4]
shl %EDX, 6
add %EDX, %ECX
and %EDX, 131008
and %EAX, -131009
or %EDX, %EAX
mov DWORD PTR [b], %EDX
ret
instead of:
plus2:
mov %EAX, DWORD PTR [b]
mov %ECX, %EAX
shr %ECX, 6
and %ECX, 2047
add %ECX, DWORD PTR [%ESP + 4]
shl %ECX, 6
and %ECX, 131008
and %EAX, -131009
or %ECX, %EAX
mov DWORD PTR [b], %ECX
ret
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23385 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-18 06:30:59 +00:00
|
|
|
Op0BO->getName());
|
|
|
|
InsertNewInstBefore(YS, I); // (Y << C)
|
|
|
|
Instruction *XM =
|
2006-01-06 07:12:35 +00:00
|
|
|
BinaryOperator::createAnd(V1, ConstantExpr::getShl(CC, Op1),
|
Compile
struct S { unsigned int i : 6, j : 11, k : 15; } b;
void plus2 (unsigned int x) {
b.j += x;
}
to:
plus2:
mov %EAX, DWORD PTR [b]
mov %ECX, %EAX
and %ECX, 131008
mov %EDX, DWORD PTR [%ESP + 4]
shl %EDX, 6
add %EDX, %ECX
and %EDX, 131008
and %EAX, -131009
or %EDX, %EAX
mov DWORD PTR [b], %EDX
ret
instead of:
plus2:
mov %EAX, DWORD PTR [b]
mov %ECX, %EAX
shr %ECX, 6
and %ECX, 2047
add %ECX, DWORD PTR [%ESP + 4]
shl %ECX, 6
and %ECX, 131008
and %EAX, -131009
or %ECX, %EAX
mov DWORD PTR [b], %ECX
ret
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23385 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-18 06:30:59 +00:00
|
|
|
V1->getName()+".mask");
|
|
|
|
InsertNewInstBefore(XM, I); // X & (CC << C)
|
|
|
|
|
|
|
|
return BinaryOperator::create(Op0BO->getOpcode(), YS, XM);
|
|
|
|
}
|
2006-01-06 07:12:35 +00:00
|
|
|
|
implement shift.ll:test25. This compiles:
struct S { unsigned int i : 6, j : 11, k : 15; } b;
void plus3 (unsigned int x) {
b.k += x;
}
to:
_plus3:
lis r2, ha16(L_b$non_lazy_ptr)
lwz r2, lo16(L_b$non_lazy_ptr)(r2)
lwz r3, 0(r2)
rlwinm r4, r3, 0, 0, 14
add r4, r4, r3
rlwimi r4, r3, 0, 15, 31
stw r4, 0(r2)
blr
instead of:
_plus3:
lis r2, ha16(L_b$non_lazy_ptr)
lwz r2, lo16(L_b$non_lazy_ptr)(r2)
lwz r4, 0(r2)
srwi r5, r4, 17
add r3, r5, r3
slwi r3, r3, 17
rlwimi r3, r4, 0, 15, 31
stw r3, 0(r2)
blr
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23381 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-18 05:12:10 +00:00
|
|
|
break;
|
2006-01-06 07:12:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// If the operand is an bitwise operator with a constant RHS, and the
|
|
|
|
// shift is the only use, we can pull it out of the shift.
|
|
|
|
if (ConstantInt *Op0C = dyn_cast<ConstantInt>(Op0BO->getOperand(1))) {
|
|
|
|
bool isValid = true; // Valid only for And, Or, Xor
|
|
|
|
bool highBitSet = false; // Transform if high bit of constant set?
|
|
|
|
|
|
|
|
switch (Op0BO->getOpcode()) {
|
2003-08-12 21:53:41 +00:00
|
|
|
default: isValid = false; break; // Do not perform transform!
|
2004-10-08 03:46:20 +00:00
|
|
|
case Instruction::Add:
|
|
|
|
isValid = isLeftShift;
|
|
|
|
break;
|
2003-08-12 21:53:41 +00:00
|
|
|
case Instruction::Or:
|
|
|
|
case Instruction::Xor:
|
|
|
|
highBitSet = false;
|
|
|
|
break;
|
|
|
|
case Instruction::And:
|
|
|
|
highBitSet = true;
|
|
|
|
break;
|
2006-01-06 07:12:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// If this is a signed shift right, and the high bit is modified
|
|
|
|
// by the logical operation, do not perform the transformation.
|
|
|
|
// The highBitSet boolean indicates the value of the high bit of
|
|
|
|
// the constant which would cause it to be modified for this
|
|
|
|
// operation.
|
|
|
|
//
|
2006-01-06 07:22:22 +00:00
|
|
|
if (isValid && !isLeftShift && isSignedShift) {
|
2006-01-06 07:12:35 +00:00
|
|
|
uint64_t Val = Op0C->getRawValue();
|
|
|
|
isValid = ((Val & (1 << (TypeBits-1))) != 0) == highBitSet;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isValid) {
|
|
|
|
Constant *NewRHS = ConstantExpr::get(I.getOpcode(), Op0C, Op1);
|
|
|
|
|
|
|
|
Instruction *NewShift =
|
|
|
|
new ShiftInst(I.getOpcode(), Op0BO->getOperand(0), Op1,
|
|
|
|
Op0BO->getName());
|
|
|
|
Op0BO->setName("");
|
|
|
|
InsertNewInstBefore(NewShift, I);
|
|
|
|
|
|
|
|
return BinaryOperator::create(Op0BO->getOpcode(), NewShift,
|
|
|
|
NewRHS);
|
2003-08-12 21:53:41 +00:00
|
|
|
}
|
implement shift.ll:test25. This compiles:
struct S { unsigned int i : 6, j : 11, k : 15; } b;
void plus3 (unsigned int x) {
b.k += x;
}
to:
_plus3:
lis r2, ha16(L_b$non_lazy_ptr)
lwz r2, lo16(L_b$non_lazy_ptr)(r2)
lwz r3, 0(r2)
rlwinm r4, r3, 0, 0, 14
add r4, r4, r3
rlwimi r4, r3, 0, 15, 31
stw r4, 0(r2)
blr
instead of:
_plus3:
lis r2, ha16(L_b$non_lazy_ptr)
lwz r2, lo16(L_b$non_lazy_ptr)(r2)
lwz r4, 0(r2)
srwi r5, r4, 17
add r3, r5, r3
slwi r3, r3, 17
rlwimi r3, r4, 0, 15, 31
stw r3, 0(r2)
blr
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23381 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-18 05:12:10 +00:00
|
|
|
}
|
2005-01-01 16:22:27 +00:00
|
|
|
}
|
2006-01-06 07:12:35 +00:00
|
|
|
}
|
|
|
|
|
2006-01-06 07:52:12 +00:00
|
|
|
// Find out if this is a shift of a shift by a constant.
|
|
|
|
ShiftInst *ShiftOp = 0;
|
2006-01-06 07:12:35 +00:00
|
|
|
if (ShiftInst *Op0SI = dyn_cast<ShiftInst>(Op0))
|
2006-01-06 07:52:12 +00:00
|
|
|
ShiftOp = Op0SI;
|
|
|
|
else if (CastInst *CI = dyn_cast<CastInst>(Op0)) {
|
|
|
|
// If this is a noop-integer case of a shift instruction, use the shift.
|
|
|
|
if (CI->getOperand(0)->getType()->isInteger() &&
|
|
|
|
CI->getOperand(0)->getType()->getPrimitiveSizeInBits() ==
|
|
|
|
CI->getType()->getPrimitiveSizeInBits() &&
|
|
|
|
isa<ShiftInst>(CI->getOperand(0))) {
|
|
|
|
ShiftOp = cast<ShiftInst>(CI->getOperand(0));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ShiftOp && isa<ConstantUInt>(ShiftOp->getOperand(1))) {
|
|
|
|
// Find the operands and properties of the input shift. Note that the
|
|
|
|
// signedness of the input shift may differ from the current shift if there
|
|
|
|
// is a noop cast between the two.
|
|
|
|
bool isShiftOfLeftShift = ShiftOp->getOpcode() == Instruction::Shl;
|
|
|
|
bool isShiftOfSignedShift = ShiftOp->getType()->isSigned();
|
2006-01-07 01:32:28 +00:00
|
|
|
bool isShiftOfUnsignedShift = !isShiftOfSignedShift;
|
2006-01-06 07:52:12 +00:00
|
|
|
|
|
|
|
ConstantUInt *ShiftAmt1C = cast<ConstantUInt>(ShiftOp->getOperand(1));
|
|
|
|
|
|
|
|
unsigned ShiftAmt1 = (unsigned)ShiftAmt1C->getValue();
|
|
|
|
unsigned ShiftAmt2 = (unsigned)Op1->getValue();
|
|
|
|
|
|
|
|
// Check for (A << c1) << c2 and (A >> c1) >> c2.
|
|
|
|
if (isLeftShift == isShiftOfLeftShift) {
|
|
|
|
// Do not fold these shifts if the first one is signed and the second one
|
|
|
|
// is unsigned and this is a right shift. Further, don't do any folding
|
|
|
|
// on them.
|
|
|
|
if (isShiftOfSignedShift && isUnsignedShift && !isLeftShift)
|
|
|
|
return 0;
|
2006-01-06 07:12:35 +00:00
|
|
|
|
2006-01-06 07:52:12 +00:00
|
|
|
unsigned Amt = ShiftAmt1+ShiftAmt2; // Fold into one big shift.
|
|
|
|
if (Amt > Op0->getType()->getPrimitiveSizeInBits())
|
|
|
|
Amt = Op0->getType()->getPrimitiveSizeInBits();
|
2006-01-06 07:12:35 +00:00
|
|
|
|
2006-01-06 07:52:12 +00:00
|
|
|
Value *Op = ShiftOp->getOperand(0);
|
|
|
|
if (isShiftOfSignedShift != isSignedShift)
|
|
|
|
Op = InsertNewInstBefore(new CastInst(Op, I.getType(), "tmp"), I);
|
|
|
|
return new ShiftInst(I.getOpcode(), Op,
|
|
|
|
ConstantUInt::get(Type::UByteTy, Amt));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check for (A << c1) >> c2 or (A >> c1) << c2. If we are dealing with
|
|
|
|
// signed types, we can only support the (A >> c1) << c2 configuration,
|
|
|
|
// because it can not turn an arbitrary bit of A into a sign bit.
|
|
|
|
if (isUnsignedShift || isLeftShift) {
|
|
|
|
// Calculate bitmask for what gets shifted off the edge.
|
|
|
|
Constant *C = ConstantIntegral::getAllOnesValue(I.getType());
|
|
|
|
if (isLeftShift)
|
|
|
|
C = ConstantExpr::getShl(C, ShiftAmt1C);
|
|
|
|
else
|
2006-01-07 01:32:28 +00:00
|
|
|
C = ConstantExpr::getUShr(C, ShiftAmt1C);
|
2006-01-06 07:52:12 +00:00
|
|
|
|
|
|
|
Value *Op = ShiftOp->getOperand(0);
|
|
|
|
if (isShiftOfSignedShift != isSignedShift)
|
|
|
|
Op = InsertNewInstBefore(new CastInst(Op, I.getType(),Op->getName()),I);
|
|
|
|
|
|
|
|
Instruction *Mask =
|
|
|
|
BinaryOperator::createAnd(Op, C, Op->getName()+".mask");
|
|
|
|
InsertNewInstBefore(Mask, I);
|
|
|
|
|
|
|
|
// Figure out what flavor of shift we should use...
|
2006-01-07 01:32:28 +00:00
|
|
|
if (ShiftAmt1 == ShiftAmt2) {
|
2006-01-06 07:52:12 +00:00
|
|
|
return ReplaceInstUsesWith(I, Mask); // (A << c) >> c === A & c2
|
2006-01-07 01:32:28 +00:00
|
|
|
} else if (ShiftAmt1 < ShiftAmt2) {
|
2006-01-06 07:52:12 +00:00
|
|
|
return new ShiftInst(I.getOpcode(), Mask,
|
|
|
|
ConstantUInt::get(Type::UByteTy, ShiftAmt2-ShiftAmt1));
|
2006-01-07 01:32:28 +00:00
|
|
|
} else if (isShiftOfUnsignedShift || isShiftOfLeftShift) {
|
|
|
|
if (isShiftOfUnsignedShift && !isShiftOfLeftShift && isSignedShift) {
|
|
|
|
// Make sure to emit an unsigned shift right, not a signed one.
|
|
|
|
Mask = InsertNewInstBefore(new CastInst(Mask,
|
|
|
|
Mask->getType()->getUnsignedVersion(),
|
|
|
|
Op->getName()), I);
|
|
|
|
Mask = new ShiftInst(Instruction::Shr, Mask,
|
2006-01-06 07:52:12 +00:00
|
|
|
ConstantUInt::get(Type::UByteTy, ShiftAmt1-ShiftAmt2));
|
2006-01-07 01:32:28 +00:00
|
|
|
InsertNewInstBefore(Mask, I);
|
|
|
|
return new CastInst(Mask, I.getType());
|
|
|
|
} else {
|
|
|
|
return new ShiftInst(ShiftOp->getOpcode(), Mask,
|
|
|
|
ConstantUInt::get(Type::UByteTy, ShiftAmt1-ShiftAmt2));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// (X >>s C1) << C2 where C1 > C2 === (X >>s (C1-C2)) & mask
|
|
|
|
Op = InsertNewInstBefore(new CastInst(Mask,
|
|
|
|
I.getType()->getSignedVersion(),
|
|
|
|
Mask->getName()), I);
|
|
|
|
Instruction *Shift =
|
|
|
|
new ShiftInst(ShiftOp->getOpcode(), Op,
|
|
|
|
ConstantUInt::get(Type::UByteTy, ShiftAmt1-ShiftAmt2));
|
|
|
|
InsertNewInstBefore(Shift, I);
|
|
|
|
|
|
|
|
C = ConstantIntegral::getAllOnesValue(Shift->getType());
|
|
|
|
C = ConstantExpr::getShl(C, Op1);
|
|
|
|
Mask = BinaryOperator::createAnd(Shift, C, Op->getName()+".mask");
|
|
|
|
InsertNewInstBefore(Mask, I);
|
|
|
|
return new CastInst(Mask, I.getType());
|
2006-01-06 07:52:12 +00:00
|
|
|
}
|
|
|
|
} else {
|
2006-01-07 01:32:28 +00:00
|
|
|
// We can handle signed (X << C1) >>s C2 if it's a sign extend. In
|
2006-01-06 07:52:12 +00:00
|
|
|
// this case, C1 == C2 and C1 is 8, 16, or 32.
|
|
|
|
if (ShiftAmt1 == ShiftAmt2) {
|
|
|
|
const Type *SExtType = 0;
|
2006-04-28 22:21:41 +00:00
|
|
|
switch (Op0->getType()->getPrimitiveSizeInBits() - ShiftAmt1) {
|
2006-01-06 07:52:12 +00:00
|
|
|
case 8 : SExtType = Type::SByteTy; break;
|
|
|
|
case 16: SExtType = Type::ShortTy; break;
|
|
|
|
case 32: SExtType = Type::IntTy; break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (SExtType) {
|
|
|
|
Instruction *NewTrunc = new CastInst(ShiftOp->getOperand(0),
|
|
|
|
SExtType, "sext");
|
|
|
|
InsertNewInstBefore(NewTrunc, I);
|
|
|
|
return new CastInst(NewTrunc, I.getType());
|
2003-07-24 17:52:58 +00:00
|
|
|
}
|
|
|
|
}
|
2006-01-06 07:12:35 +00:00
|
|
|
}
|
2006-01-06 07:52:12 +00:00
|
|
|
}
|
2002-05-06 16:14:14 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2002-05-02 17:06:02 +00:00
|
|
|
|
2005-10-29 04:36:15 +00:00
|
|
|
/// DecomposeSimpleLinearExpr - Analyze 'Val', seeing if it is a simple linear
|
|
|
|
/// expression. If so, decompose it, returning some value X, such that Val is
|
|
|
|
/// X*Scale+Offset.
|
|
|
|
///
|
|
|
|
static Value *DecomposeSimpleLinearExpr(Value *Val, unsigned &Scale,
|
|
|
|
unsigned &Offset) {
|
|
|
|
assert(Val->getType() == Type::UIntTy && "Unexpected allocation size type!");
|
|
|
|
if (ConstantUInt *CI = dyn_cast<ConstantUInt>(Val)) {
|
|
|
|
Offset = CI->getValue();
|
|
|
|
Scale = 1;
|
|
|
|
return ConstantUInt::get(Type::UIntTy, 0);
|
|
|
|
} else if (Instruction *I = dyn_cast<Instruction>(Val)) {
|
|
|
|
if (I->getNumOperands() == 2) {
|
|
|
|
if (ConstantUInt *CUI = dyn_cast<ConstantUInt>(I->getOperand(1))) {
|
|
|
|
if (I->getOpcode() == Instruction::Shl) {
|
|
|
|
// This is a value scaled by '1 << the shift amt'.
|
|
|
|
Scale = 1U << CUI->getValue();
|
|
|
|
Offset = 0;
|
|
|
|
return I->getOperand(0);
|
|
|
|
} else if (I->getOpcode() == Instruction::Mul) {
|
|
|
|
// This value is scaled by 'CUI'.
|
|
|
|
Scale = CUI->getValue();
|
|
|
|
Offset = 0;
|
|
|
|
return I->getOperand(0);
|
|
|
|
} else if (I->getOpcode() == Instruction::Add) {
|
|
|
|
// We have X+C. Check to see if we really have (X*C2)+C1, where C1 is
|
|
|
|
// divisible by C2.
|
|
|
|
unsigned SubScale;
|
|
|
|
Value *SubVal = DecomposeSimpleLinearExpr(I->getOperand(0), SubScale,
|
|
|
|
Offset);
|
|
|
|
Offset += CUI->getValue();
|
|
|
|
if (SubScale > 1 && (Offset % SubScale == 0)) {
|
|
|
|
Scale = SubScale;
|
|
|
|
return SubVal;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, we can't look past this.
|
|
|
|
Scale = 1;
|
|
|
|
Offset = 0;
|
|
|
|
return Val;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-10-24 06:03:58 +00:00
|
|
|
/// PromoteCastOfAllocation - If we find a cast of an allocation instruction,
|
|
|
|
/// try to eliminate the cast by moving the type information into the alloc.
|
|
|
|
Instruction *InstCombiner::PromoteCastOfAllocation(CastInst &CI,
|
|
|
|
AllocationInst &AI) {
|
|
|
|
const PointerType *PTy = dyn_cast<PointerType>(CI.getType());
|
2005-10-27 05:53:56 +00:00
|
|
|
if (!PTy) return 0; // Not casting the allocation to a pointer type.
|
2005-10-24 06:03:58 +00:00
|
|
|
|
2005-10-24 06:22:12 +00:00
|
|
|
// Remove any uses of AI that are dead.
|
|
|
|
assert(!CI.use_empty() && "Dead instructions should be removed earlier!");
|
|
|
|
std::vector<Instruction*> DeadUsers;
|
|
|
|
for (Value::use_iterator UI = AI.use_begin(), E = AI.use_end(); UI != E; ) {
|
|
|
|
Instruction *User = cast<Instruction>(*UI++);
|
|
|
|
if (isInstructionTriviallyDead(User)) {
|
|
|
|
while (UI != E && *UI == User)
|
|
|
|
++UI; // If this instruction uses AI more than once, don't break UI.
|
|
|
|
|
|
|
|
// Add operands to the worklist.
|
|
|
|
AddUsesToWorkList(*User);
|
|
|
|
++NumDeadInst;
|
|
|
|
DEBUG(std::cerr << "IC: DCE: " << *User);
|
|
|
|
|
|
|
|
User->eraseFromParent();
|
|
|
|
removeFromWorkList(User);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-10-24 06:03:58 +00:00
|
|
|
// Get the type really allocated and the type casted to.
|
|
|
|
const Type *AllocElTy = AI.getAllocatedType();
|
|
|
|
const Type *CastElTy = PTy->getElementType();
|
|
|
|
if (!AllocElTy->isSized() || !CastElTy->isSized()) return 0;
|
2005-10-24 06:26:18 +00:00
|
|
|
|
|
|
|
unsigned AllocElTyAlign = TD->getTypeSize(AllocElTy);
|
|
|
|
unsigned CastElTyAlign = TD->getTypeSize(CastElTy);
|
|
|
|
if (CastElTyAlign < AllocElTyAlign) return 0;
|
|
|
|
|
2005-10-24 06:35:18 +00:00
|
|
|
// If the allocation has multiple uses, only promote it if we are strictly
|
|
|
|
// increasing the alignment of the resultant allocation. If we keep it the
|
|
|
|
// same, we open the door to infinite loops of various kinds.
|
|
|
|
if (!AI.hasOneUse() && CastElTyAlign == AllocElTyAlign) return 0;
|
|
|
|
|
2005-10-24 06:03:58 +00:00
|
|
|
uint64_t AllocElTySize = TD->getTypeSize(AllocElTy);
|
|
|
|
uint64_t CastElTySize = TD->getTypeSize(CastElTy);
|
2005-10-27 05:53:56 +00:00
|
|
|
if (CastElTySize == 0 || AllocElTySize == 0) return 0;
|
2005-10-24 06:26:18 +00:00
|
|
|
|
2005-10-29 03:19:53 +00:00
|
|
|
// See if we can satisfy the modulus by pulling a scale out of the array
|
|
|
|
// size argument.
|
2005-10-29 04:36:15 +00:00
|
|
|
unsigned ArraySizeScale, ArrayOffset;
|
|
|
|
Value *NumElements = // See if the array size is a decomposable linear expr.
|
|
|
|
DecomposeSimpleLinearExpr(AI.getOperand(0), ArraySizeScale, ArrayOffset);
|
|
|
|
|
2005-10-29 03:19:53 +00:00
|
|
|
// If we can now satisfy the modulus, by using a non-1 scale, we really can
|
|
|
|
// do the xform.
|
2005-10-29 04:36:15 +00:00
|
|
|
if ((AllocElTySize*ArraySizeScale) % CastElTySize != 0 ||
|
|
|
|
(AllocElTySize*ArrayOffset ) % CastElTySize != 0) return 0;
|
2005-10-27 06:12:00 +00:00
|
|
|
|
2005-10-29 03:19:53 +00:00
|
|
|
unsigned Scale = (AllocElTySize*ArraySizeScale)/CastElTySize;
|
|
|
|
Value *Amt = 0;
|
|
|
|
if (Scale == 1) {
|
|
|
|
Amt = NumElements;
|
|
|
|
} else {
|
|
|
|
Amt = ConstantUInt::get(Type::UIntTy, Scale);
|
|
|
|
if (ConstantUInt *CI = dyn_cast<ConstantUInt>(NumElements))
|
|
|
|
Amt = ConstantExpr::getMul(CI, cast<ConstantUInt>(Amt));
|
|
|
|
else if (Scale != 1) {
|
|
|
|
Instruction *Tmp = BinaryOperator::createMul(Amt, NumElements, "tmp");
|
|
|
|
Amt = InsertNewInstBefore(Tmp, AI);
|
2005-10-27 06:12:00 +00:00
|
|
|
}
|
2005-10-27 05:53:56 +00:00
|
|
|
}
|
|
|
|
|
2005-10-29 04:36:15 +00:00
|
|
|
if (unsigned Offset = (AllocElTySize*ArrayOffset)/CastElTySize) {
|
|
|
|
Value *Off = ConstantUInt::get(Type::UIntTy, Offset);
|
|
|
|
Instruction *Tmp = BinaryOperator::createAdd(Amt, Off, "tmp");
|
|
|
|
Amt = InsertNewInstBefore(Tmp, AI);
|
|
|
|
}
|
|
|
|
|
2005-10-24 06:03:58 +00:00
|
|
|
std::string Name = AI.getName(); AI.setName("");
|
|
|
|
AllocationInst *New;
|
|
|
|
if (isa<MallocInst>(AI))
|
2005-11-05 09:21:28 +00:00
|
|
|
New = new MallocInst(CastElTy, Amt, AI.getAlignment(), Name);
|
2005-10-24 06:03:58 +00:00
|
|
|
else
|
2005-11-05 09:21:28 +00:00
|
|
|
New = new AllocaInst(CastElTy, Amt, AI.getAlignment(), Name);
|
2005-10-24 06:03:58 +00:00
|
|
|
InsertNewInstBefore(New, AI);
|
2005-10-24 06:35:18 +00:00
|
|
|
|
|
|
|
// If the allocation has multiple uses, insert a cast and change all things
|
|
|
|
// that used it to use the new cast. This will also hack on CI, but it will
|
|
|
|
// die soon.
|
|
|
|
if (!AI.hasOneUse()) {
|
|
|
|
AddUsesToWorkList(AI);
|
|
|
|
CastInst *NewCast = new CastInst(New, AI.getType(), "tmpcast");
|
|
|
|
InsertNewInstBefore(NewCast, AI);
|
|
|
|
AI.replaceAllUsesWith(NewCast);
|
|
|
|
}
|
2005-10-24 06:03:58 +00:00
|
|
|
return ReplaceInstUsesWith(CI, New);
|
|
|
|
}
|
|
|
|
|
Implement simple promotion for cast elimination in instcombine. This is
currently very limited, but can be extended in the future. For example,
we now compile:
uint %test30(uint %c1) {
%c2 = cast uint %c1 to ubyte
%c3 = xor ubyte %c2, 1
%c4 = cast ubyte %c3 to uint
ret uint %c4
}
to:
_xor:
movzbl 4(%esp), %eax
xorl $1, %eax
ret
instead of:
_xor:
movb $1, %al
xorb 4(%esp), %al
movzbl %al, %eax
ret
More impressively, we now compile:
struct B { unsigned bit : 1; };
void xor(struct B *b) { b->bit = b->bit ^ 1; }
To (X86/PPC):
_xor:
movl 4(%esp), %eax
xorl $-2147483648, (%eax)
ret
_xor:
lwz r2, 0(r3)
xoris r2, r2, 32768
stw r2, 0(r3)
blr
instead of (X86/PPC):
_xor:
movl 4(%esp), %eax
movl (%eax), %ecx
movl %ecx, %edx
shrl $31, %edx
# TRUNCATE movb %dl, %dl
xorb $1, %dl
movzbl %dl, %edx
andl $2147483647, %ecx
shll $31, %edx
orl %ecx, %edx
movl %edx, (%eax)
ret
_xor:
lwz r2, 0(r3)
srwi r4, r2, 31
xori r4, r4, 1
rlwimi r2, r4, 31, 0, 0
stw r2, 0(r3)
blr
This implements InstCombine/cast.ll:test30.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@28273 91177308-0d34-0410-b5e6-96231b3b80d8
2006-05-13 02:06:03 +00:00
|
|
|
/// CanEvaluateInDifferentType - Return true if we can take the specified value
|
|
|
|
/// and return it without inserting any new casts. This is used by code that
|
|
|
|
/// tries to decide whether promoting or shrinking integer operations to wider
|
|
|
|
/// or smaller types will allow us to eliminate a truncate or extend.
|
|
|
|
static bool CanEvaluateInDifferentType(Value *V, const Type *Ty,
|
|
|
|
int &NumCastsRemoved) {
|
|
|
|
if (isa<Constant>(V)) return true;
|
|
|
|
|
|
|
|
Instruction *I = dyn_cast<Instruction>(V);
|
|
|
|
if (!I || !I->hasOneUse()) return false;
|
|
|
|
|
|
|
|
switch (I->getOpcode()) {
|
|
|
|
case Instruction::And:
|
|
|
|
case Instruction::Or:
|
|
|
|
case Instruction::Xor:
|
|
|
|
// These operators can all arbitrarily be extended or truncated.
|
|
|
|
return CanEvaluateInDifferentType(I->getOperand(0), Ty, NumCastsRemoved) &&
|
|
|
|
CanEvaluateInDifferentType(I->getOperand(1), Ty, NumCastsRemoved);
|
|
|
|
case Instruction::Cast:
|
|
|
|
// If this is a cast from the destination type, we can trivially eliminate
|
|
|
|
// it, and this will remove a cast overall.
|
|
|
|
if (I->getOperand(0)->getType() == Ty) {
|
|
|
|
++NumCastsRemoved;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
// TODO: Can handle more cases here.
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// EvaluateInDifferentType - Given an expression that
|
|
|
|
/// CanEvaluateInDifferentType returns true for, actually insert the code to
|
|
|
|
/// evaluate the expression.
|
|
|
|
Value *InstCombiner::EvaluateInDifferentType(Value *V, const Type *Ty) {
|
|
|
|
if (Constant *C = dyn_cast<Constant>(V))
|
|
|
|
return ConstantExpr::getCast(C, Ty);
|
|
|
|
|
|
|
|
// Otherwise, it must be an instruction.
|
|
|
|
Instruction *I = cast<Instruction>(V);
|
2006-05-20 23:14:03 +00:00
|
|
|
Instruction *Res = 0;
|
Implement simple promotion for cast elimination in instcombine. This is
currently very limited, but can be extended in the future. For example,
we now compile:
uint %test30(uint %c1) {
%c2 = cast uint %c1 to ubyte
%c3 = xor ubyte %c2, 1
%c4 = cast ubyte %c3 to uint
ret uint %c4
}
to:
_xor:
movzbl 4(%esp), %eax
xorl $1, %eax
ret
instead of:
_xor:
movb $1, %al
xorb 4(%esp), %al
movzbl %al, %eax
ret
More impressively, we now compile:
struct B { unsigned bit : 1; };
void xor(struct B *b) { b->bit = b->bit ^ 1; }
To (X86/PPC):
_xor:
movl 4(%esp), %eax
xorl $-2147483648, (%eax)
ret
_xor:
lwz r2, 0(r3)
xoris r2, r2, 32768
stw r2, 0(r3)
blr
instead of (X86/PPC):
_xor:
movl 4(%esp), %eax
movl (%eax), %ecx
movl %ecx, %edx
shrl $31, %edx
# TRUNCATE movb %dl, %dl
xorb $1, %dl
movzbl %dl, %edx
andl $2147483647, %ecx
shll $31, %edx
orl %ecx, %edx
movl %edx, (%eax)
ret
_xor:
lwz r2, 0(r3)
srwi r4, r2, 31
xori r4, r4, 1
rlwimi r2, r4, 31, 0, 0
stw r2, 0(r3)
blr
This implements InstCombine/cast.ll:test30.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@28273 91177308-0d34-0410-b5e6-96231b3b80d8
2006-05-13 02:06:03 +00:00
|
|
|
switch (I->getOpcode()) {
|
|
|
|
case Instruction::And:
|
|
|
|
case Instruction::Or:
|
|
|
|
case Instruction::Xor: {
|
|
|
|
Value *LHS = EvaluateInDifferentType(I->getOperand(0), Ty);
|
|
|
|
Value *RHS = EvaluateInDifferentType(I->getOperand(1), Ty);
|
|
|
|
Res = BinaryOperator::create((Instruction::BinaryOps)I->getOpcode(),
|
|
|
|
LHS, RHS, I->getName());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Instruction::Cast:
|
|
|
|
// If this is a cast from the destination type, return the input.
|
|
|
|
if (I->getOperand(0)->getType() == Ty)
|
|
|
|
return I->getOperand(0);
|
|
|
|
|
|
|
|
// TODO: Can handle more cases here.
|
|
|
|
assert(0 && "Unreachable!");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return InsertNewInstBefore(Res, *I);
|
|
|
|
}
|
|
|
|
|
2005-10-24 06:03:58 +00:00
|
|
|
|
2002-05-02 17:06:02 +00:00
|
|
|
// CastInst simplification
|
2002-04-18 17:39:14 +00:00
|
|
|
//
|
2002-06-25 16:13:24 +00:00
|
|
|
Instruction *InstCombiner::visitCastInst(CastInst &CI) {
|
2003-06-23 21:59:52 +00:00
|
|
|
Value *Src = CI.getOperand(0);
|
|
|
|
|
2002-05-02 17:06:02 +00:00
|
|
|
// If the user is casting a value to the same type, eliminate this cast
|
|
|
|
// instruction...
|
2003-06-23 21:59:52 +00:00
|
|
|
if (CI.getType() == Src->getType())
|
|
|
|
return ReplaceInstUsesWith(CI, Src);
|
2002-05-02 17:06:02 +00:00
|
|
|
|
2004-10-16 18:11:37 +00:00
|
|
|
if (isa<UndefValue>(Src)) // cast undef -> undef
|
|
|
|
return ReplaceInstUsesWith(CI, UndefValue::get(CI.getType()));
|
|
|
|
|
2002-05-02 17:06:02 +00:00
|
|
|
// If casting the result of another cast instruction, try to eliminate this
|
|
|
|
// one!
|
|
|
|
//
|
2005-01-01 16:22:27 +00:00
|
|
|
if (CastInst *CSrc = dyn_cast<CastInst>(Src)) { // A->B->C cast
|
|
|
|
Value *A = CSrc->getOperand(0);
|
|
|
|
if (isEliminableCastOfCast(A->getType(), CSrc->getType(),
|
|
|
|
CI.getType(), TD)) {
|
2002-05-02 17:06:02 +00:00
|
|
|
// This instruction now refers directly to the cast's src operand. This
|
|
|
|
// has a good chance of making CSrc dead.
|
2002-06-25 16:13:24 +00:00
|
|
|
CI.setOperand(0, CSrc->getOperand(0));
|
|
|
|
return &CI;
|
2002-05-02 17:06:02 +00:00
|
|
|
}
|
|
|
|
|
2002-08-02 20:00:25 +00:00
|
|
|
// If this is an A->B->A cast, and we are dealing with integral types, try
|
|
|
|
// to convert this into a logical 'and' instruction.
|
|
|
|
//
|
2005-04-21 23:48:37 +00:00
|
|
|
if (A->getType()->isInteger() &&
|
2002-09-03 01:08:28 +00:00
|
|
|
CI.getType()->isInteger() && CSrc->getType()->isInteger() &&
|
2005-01-01 16:22:27 +00:00
|
|
|
CSrc->getType()->isUnsigned() && // B->A cast must zero extend
|
2005-04-24 06:59:08 +00:00
|
|
|
CSrc->getType()->getPrimitiveSizeInBits() <
|
|
|
|
CI.getType()->getPrimitiveSizeInBits()&&
|
|
|
|
A->getType()->getPrimitiveSizeInBits() ==
|
|
|
|
CI.getType()->getPrimitiveSizeInBits()) {
|
2002-08-02 20:00:25 +00:00
|
|
|
assert(CSrc->getType() != Type::ULongTy &&
|
|
|
|
"Cannot have type bigger than ulong!");
|
2006-02-07 07:00:41 +00:00
|
|
|
uint64_t AndValue = CSrc->getType()->getIntegralTypeMask();
|
2005-01-01 16:22:27 +00:00
|
|
|
Constant *AndOp = ConstantUInt::get(A->getType()->getUnsignedVersion(),
|
|
|
|
AndValue);
|
|
|
|
AndOp = ConstantExpr::getCast(AndOp, A->getType());
|
|
|
|
Instruction *And = BinaryOperator::createAnd(CSrc->getOperand(0), AndOp);
|
|
|
|
if (And->getType() != CI.getType()) {
|
|
|
|
And->setName(CSrc->getName()+".mask");
|
|
|
|
InsertNewInstBefore(And, CI);
|
|
|
|
And = new CastInst(And, CI.getType());
|
|
|
|
}
|
|
|
|
return And;
|
2002-08-02 20:00:25 +00:00
|
|
|
}
|
|
|
|
}
|
2006-02-07 06:56:34 +00:00
|
|
|
|
2004-05-25 04:29:21 +00:00
|
|
|
// If this is a cast to bool, turn it into the appropriate setne instruction.
|
|
|
|
if (CI.getType() == Type::BoolTy)
|
2004-06-10 02:07:29 +00:00
|
|
|
return BinaryOperator::createSetNE(CI.getOperand(0),
|
2004-05-25 04:29:21 +00:00
|
|
|
Constant::getNullValue(CI.getOperand(0)->getType()));
|
|
|
|
|
2006-02-07 06:56:34 +00:00
|
|
|
// See if we can simplify any instructions used by the LHS whose sole
|
|
|
|
// purpose is to compute bits we don't care about.
|
2006-02-11 09:31:47 +00:00
|
|
|
if (CI.getType()->isInteger() && CI.getOperand(0)->getType()->isIntegral()) {
|
|
|
|
uint64_t KnownZero, KnownOne;
|
|
|
|
if (SimplifyDemandedBits(&CI, CI.getType()->getIntegralTypeMask(),
|
|
|
|
KnownZero, KnownOne))
|
|
|
|
return &CI;
|
|
|
|
}
|
2006-02-07 06:56:34 +00:00
|
|
|
|
2003-06-21 23:12:02 +00:00
|
|
|
// If casting the result of a getelementptr instruction with no offset, turn
|
|
|
|
// this into a cast of the original pointer!
|
|
|
|
//
|
2003-06-23 21:59:52 +00:00
|
|
|
if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Src)) {
|
2003-06-21 23:12:02 +00:00
|
|
|
bool AllZeroOperands = true;
|
|
|
|
for (unsigned i = 1, e = GEP->getNumOperands(); i != e; ++i)
|
|
|
|
if (!isa<Constant>(GEP->getOperand(i)) ||
|
|
|
|
!cast<Constant>(GEP->getOperand(i))->isNullValue()) {
|
|
|
|
AllZeroOperands = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (AllZeroOperands) {
|
|
|
|
CI.setOperand(0, GEP->getOperand(0));
|
|
|
|
return &CI;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-11-02 05:57:39 +00:00
|
|
|
// If we are casting a malloc or alloca to a pointer to a type of the same
|
|
|
|
// size, rewrite the allocation instruction to allocate the "right" type.
|
|
|
|
//
|
|
|
|
if (AllocationInst *AI = dyn_cast<AllocationInst>(Src))
|
2005-10-24 06:03:58 +00:00
|
|
|
if (Instruction *V = PromoteCastOfAllocation(CI, *AI))
|
|
|
|
return V;
|
2003-11-02 05:57:39 +00:00
|
|
|
|
2005-01-01 16:22:27 +00:00
|
|
|
if (SelectInst *SI = dyn_cast<SelectInst>(Src))
|
|
|
|
if (Instruction *NV = FoldOpIntoSelect(CI, SI, this))
|
|
|
|
return NV;
|
Fold binary expressions and casts into PHI nodes that have all constant inputs.
This takes something like this:
%A = phi int [ 3, %cond_false.0 ], [ 2, %endif.0.i ], [ 2, %endif.1.i ]
%B = div int %tmp.243, 4
and turns it into:
%A = phi int [ 3/4, %cond_false.0 ], [ 2/4, %endif.0.i ], [ 2/4, %endif.1.i ]
which is later simplified (in this case) into %A = 0.
This triggers thousands of times in spec, for example, 269 times in 176.gcc.
This is tested by InstCombine/add.ll:test23 and set.ll:test18.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16582 91177308-0d34-0410-b5e6-96231b3b80d8
2004-09-29 05:07:12 +00:00
|
|
|
if (isa<PHINode>(Src))
|
|
|
|
if (Instruction *NV = FoldOpIntoPhi(CI))
|
|
|
|
return NV;
|
2006-04-12 18:09:35 +00:00
|
|
|
|
|
|
|
// If the source and destination are pointers, and this cast is equivalent to
|
|
|
|
// a getelementptr X, 0, 0, 0... turn it into the appropriate getelementptr.
|
|
|
|
// This can enhance SROA and other transforms that want type-safe pointers.
|
|
|
|
if (const PointerType *DstPTy = dyn_cast<PointerType>(CI.getType()))
|
|
|
|
if (const PointerType *SrcPTy = dyn_cast<PointerType>(Src->getType())) {
|
|
|
|
const Type *DstTy = DstPTy->getElementType();
|
|
|
|
const Type *SrcTy = SrcPTy->getElementType();
|
|
|
|
|
|
|
|
Constant *ZeroUInt = Constant::getNullValue(Type::UIntTy);
|
|
|
|
unsigned NumZeros = 0;
|
|
|
|
while (SrcTy != DstTy &&
|
|
|
|
isa<CompositeType>(SrcTy) && !isa<PointerType>(SrcTy)) {
|
|
|
|
SrcTy = cast<CompositeType>(SrcTy)->getTypeAtIndex(ZeroUInt);
|
|
|
|
++NumZeros;
|
|
|
|
}
|
Fold binary expressions and casts into PHI nodes that have all constant inputs.
This takes something like this:
%A = phi int [ 3, %cond_false.0 ], [ 2, %endif.0.i ], [ 2, %endif.1.i ]
%B = div int %tmp.243, 4
and turns it into:
%A = phi int [ 3/4, %cond_false.0 ], [ 2/4, %endif.0.i ], [ 2/4, %endif.1.i ]
which is later simplified (in this case) into %A = 0.
This triggers thousands of times in spec, for example, 269 times in 176.gcc.
This is tested by InstCombine/add.ll:test23 and set.ll:test18.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16582 91177308-0d34-0410-b5e6-96231b3b80d8
2004-09-29 05:07:12 +00:00
|
|
|
|
2006-04-12 18:09:35 +00:00
|
|
|
// If we found a path from the src to dest, create the getelementptr now.
|
|
|
|
if (SrcTy == DstTy) {
|
|
|
|
std::vector<Value*> Idxs(NumZeros+1, ZeroUInt);
|
|
|
|
return new GetElementPtrInst(Src, Idxs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-07-24 17:35:25 +00:00
|
|
|
// If the source value is an instruction with only this use, we can attempt to
|
|
|
|
// propagate the cast into the instruction. Also, only handle integral types
|
|
|
|
// for now.
|
|
|
|
if (Instruction *SrcI = dyn_cast<Instruction>(Src))
|
2003-10-15 16:48:29 +00:00
|
|
|
if (SrcI->hasOneUse() && Src->getType()->isIntegral() &&
|
2003-07-24 17:35:25 +00:00
|
|
|
CI.getType()->isInteger()) { // Don't mess with casts to bool here
|
Implement simple promotion for cast elimination in instcombine. This is
currently very limited, but can be extended in the future. For example,
we now compile:
uint %test30(uint %c1) {
%c2 = cast uint %c1 to ubyte
%c3 = xor ubyte %c2, 1
%c4 = cast ubyte %c3 to uint
ret uint %c4
}
to:
_xor:
movzbl 4(%esp), %eax
xorl $1, %eax
ret
instead of:
_xor:
movb $1, %al
xorb 4(%esp), %al
movzbl %al, %eax
ret
More impressively, we now compile:
struct B { unsigned bit : 1; };
void xor(struct B *b) { b->bit = b->bit ^ 1; }
To (X86/PPC):
_xor:
movl 4(%esp), %eax
xorl $-2147483648, (%eax)
ret
_xor:
lwz r2, 0(r3)
xoris r2, r2, 32768
stw r2, 0(r3)
blr
instead of (X86/PPC):
_xor:
movl 4(%esp), %eax
movl (%eax), %ecx
movl %ecx, %edx
shrl $31, %edx
# TRUNCATE movb %dl, %dl
xorb $1, %dl
movzbl %dl, %edx
andl $2147483647, %ecx
shll $31, %edx
orl %ecx, %edx
movl %edx, (%eax)
ret
_xor:
lwz r2, 0(r3)
srwi r4, r2, 31
xori r4, r4, 1
rlwimi r2, r4, 31, 0, 0
stw r2, 0(r3)
blr
This implements InstCombine/cast.ll:test30.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@28273 91177308-0d34-0410-b5e6-96231b3b80d8
2006-05-13 02:06:03 +00:00
|
|
|
|
|
|
|
int NumCastsRemoved = 0;
|
|
|
|
if (CanEvaluateInDifferentType(SrcI, CI.getType(), NumCastsRemoved)) {
|
|
|
|
// If this cast is a truncate, evaluting in a different type always
|
|
|
|
// eliminates the cast, so it is always a win. If this is a noop-cast
|
|
|
|
// this just removes a noop cast which isn't pointful, but simplifies
|
|
|
|
// the code. If this is a zero-extension, we need to do an AND to
|
|
|
|
// maintain the clear top-part of the computation, so we require that
|
|
|
|
// the input have eliminated at least one cast. If this is a sign
|
|
|
|
// extension, we insert two new casts (to do the extension) so we
|
|
|
|
// require that two casts have been eliminated.
|
|
|
|
bool DoXForm;
|
|
|
|
switch (getCastType(Src->getType(), CI.getType())) {
|
|
|
|
default: assert(0 && "Unknown cast type!");
|
|
|
|
case Noop:
|
|
|
|
case Truncate:
|
|
|
|
DoXForm = true;
|
|
|
|
break;
|
|
|
|
case Zeroext:
|
|
|
|
DoXForm = NumCastsRemoved >= 1;
|
|
|
|
break;
|
|
|
|
case Signext:
|
|
|
|
DoXForm = NumCastsRemoved >= 2;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (DoXForm) {
|
|
|
|
Value *Res = EvaluateInDifferentType(SrcI, CI.getType());
|
|
|
|
assert(Res->getType() == CI.getType());
|
|
|
|
switch (getCastType(Src->getType(), CI.getType())) {
|
|
|
|
default: assert(0 && "Unknown cast type!");
|
|
|
|
case Noop:
|
|
|
|
case Truncate:
|
|
|
|
// Just replace this cast with the result.
|
|
|
|
return ReplaceInstUsesWith(CI, Res);
|
|
|
|
case Zeroext: {
|
|
|
|
// We need to emit an AND to clear the high bits.
|
|
|
|
unsigned SrcBitSize = Src->getType()->getPrimitiveSizeInBits();
|
|
|
|
unsigned DestBitSize = CI.getType()->getPrimitiveSizeInBits();
|
|
|
|
assert(SrcBitSize < DestBitSize && "Not a zext?");
|
|
|
|
Constant *C = ConstantUInt::get(Type::ULongTy, (1 << SrcBitSize)-1);
|
|
|
|
C = ConstantExpr::getCast(C, CI.getType());
|
|
|
|
return BinaryOperator::createAnd(Res, C);
|
|
|
|
}
|
|
|
|
case Signext:
|
|
|
|
// We need to emit a cast to truncate, then a cast to sext.
|
|
|
|
return new CastInst(InsertCastBefore(Res, Src->getType(), CI),
|
|
|
|
CI.getType());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-07-24 17:35:25 +00:00
|
|
|
const Type *DestTy = CI.getType();
|
2005-04-24 06:59:08 +00:00
|
|
|
unsigned SrcBitSize = Src->getType()->getPrimitiveSizeInBits();
|
|
|
|
unsigned DestBitSize = DestTy->getPrimitiveSizeInBits();
|
2003-07-24 17:35:25 +00:00
|
|
|
|
|
|
|
Value *Op0 = SrcI->getNumOperands() > 0 ? SrcI->getOperand(0) : 0;
|
|
|
|
Value *Op1 = SrcI->getNumOperands() > 1 ? SrcI->getOperand(1) : 0;
|
|
|
|
|
|
|
|
switch (SrcI->getOpcode()) {
|
|
|
|
case Instruction::Add:
|
|
|
|
case Instruction::Mul:
|
|
|
|
case Instruction::And:
|
|
|
|
case Instruction::Or:
|
|
|
|
case Instruction::Xor:
|
|
|
|
// If we are discarding information, or just changing the sign, rewrite.
|
|
|
|
if (DestBitSize <= SrcBitSize && DestBitSize != 1) {
|
|
|
|
// Don't insert two casts if they cannot be eliminated. We allow two
|
|
|
|
// casts to be inserted if the sizes are the same. This could only be
|
|
|
|
// converting signedness, which is a noop.
|
2004-07-20 05:21:00 +00:00
|
|
|
if (DestBitSize == SrcBitSize || !ValueRequiresCast(Op1, DestTy,TD) ||
|
|
|
|
!ValueRequiresCast(Op0, DestTy, TD)) {
|
2003-07-24 17:35:25 +00:00
|
|
|
Value *Op0c = InsertOperandCastBefore(Op0, DestTy, SrcI);
|
|
|
|
Value *Op1c = InsertOperandCastBefore(Op1, DestTy, SrcI);
|
|
|
|
return BinaryOperator::create(cast<BinaryOperator>(SrcI)
|
|
|
|
->getOpcode(), Op0c, Op1c);
|
|
|
|
}
|
|
|
|
}
|
2005-05-06 02:07:39 +00:00
|
|
|
|
|
|
|
// cast (xor bool X, true) to int --> xor (cast bool X to int), 1
|
|
|
|
if (SrcBitSize == 1 && SrcI->getOpcode() == Instruction::Xor &&
|
|
|
|
Op1 == ConstantBool::True &&
|
|
|
|
(!Op0->hasOneUse() || !isa<SetCondInst>(Op0))) {
|
|
|
|
Value *New = InsertOperandCastBefore(Op0, DestTy, &CI);
|
|
|
|
return BinaryOperator::createXor(New,
|
|
|
|
ConstantInt::get(CI.getType(), 1));
|
|
|
|
}
|
2003-07-24 17:35:25 +00:00
|
|
|
break;
|
|
|
|
case Instruction::Shl:
|
|
|
|
// Allow changing the sign of the source operand. Do not allow changing
|
|
|
|
// the size of the shift, UNLESS the shift amount is a constant. We
|
|
|
|
// mush not change variable sized shifts to a smaller size, because it
|
|
|
|
// is undefined to shift more bits out than exist in the value.
|
|
|
|
if (DestBitSize == SrcBitSize ||
|
|
|
|
(DestBitSize < SrcBitSize && isa<Constant>(Op1))) {
|
|
|
|
Value *Op0c = InsertOperandCastBefore(Op0, DestTy, SrcI);
|
|
|
|
return new ShiftInst(Instruction::Shl, Op0c, Op1);
|
|
|
|
}
|
|
|
|
break;
|
Implement shift.ll:test23. If we are shifting right then immediately truncating
the result, turn signed shift rights into unsigned shift rights if possible.
This leads to later simplification and happens *often* in 176.gcc. For example,
this testcase:
struct xxx { unsigned int code : 8; };
enum codes { A, B, C, D, E, F };
int foo(struct xxx *P) {
if ((enum codes)P->code == A)
bar();
}
used to be compiled to:
int %foo(%struct.xxx* %P) {
%tmp.1 = getelementptr %struct.xxx* %P, int 0, uint 0 ; <uint*> [#uses=1]
%tmp.2 = load uint* %tmp.1 ; <uint> [#uses=1]
%tmp.3 = cast uint %tmp.2 to int ; <int> [#uses=1]
%tmp.4 = shl int %tmp.3, ubyte 24 ; <int> [#uses=1]
%tmp.5 = shr int %tmp.4, ubyte 24 ; <int> [#uses=1]
%tmp.6 = cast int %tmp.5 to sbyte ; <sbyte> [#uses=1]
%tmp.8 = seteq sbyte %tmp.6, 0 ; <bool> [#uses=1]
br bool %tmp.8, label %then, label %UnifiedReturnBlock
Now it is compiled to:
%tmp.1 = getelementptr %struct.xxx* %P, int 0, uint 0 ; <uint*> [#uses=1]
%tmp.2 = load uint* %tmp.1 ; <uint> [#uses=1]
%tmp.2 = cast uint %tmp.2 to sbyte ; <sbyte> [#uses=1]
%tmp.8 = seteq sbyte %tmp.2, 0 ; <bool> [#uses=1]
br bool %tmp.8, label %then, label %UnifiedReturnBlock
which is the difference between this:
foo:
subl $4, %esp
movl 8(%esp), %eax
movl (%eax), %eax
shll $24, %eax
sarl $24, %eax
testb %al, %al
jne .LBBfoo_2
and this:
foo:
subl $4, %esp
movl 8(%esp), %eax
movl (%eax), %eax
testb %al, %al
jne .LBBfoo_2
This occurs 3243 times total in the External tests, 215x in povray,
6x in each f2c'd program, 1451x in 176.gcc, 7x in crafty, 20x in perl,
25x in gap, 3x in m88ksim, 25x in ijpeg.
Maybe this will cause a little jump on gcc tommorow :)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@21715 91177308-0d34-0410-b5e6-96231b3b80d8
2005-05-06 04:18:52 +00:00
|
|
|
case Instruction::Shr:
|
|
|
|
// If this is a signed shr, and if all bits shifted in are about to be
|
|
|
|
// truncated off, turn it into an unsigned shr to allow greater
|
|
|
|
// simplifications.
|
|
|
|
if (DestBitSize < SrcBitSize && Src->getType()->isSigned() &&
|
|
|
|
isa<ConstantInt>(Op1)) {
|
|
|
|
unsigned ShiftAmt = cast<ConstantUInt>(Op1)->getValue();
|
|
|
|
if (SrcBitSize > ShiftAmt && SrcBitSize-ShiftAmt >= DestBitSize) {
|
|
|
|
// Convert to unsigned.
|
|
|
|
Value *N1 = InsertOperandCastBefore(Op0,
|
|
|
|
Op0->getType()->getUnsignedVersion(), &CI);
|
|
|
|
// Insert the new shift, which is now unsigned.
|
|
|
|
N1 = InsertNewInstBefore(new ShiftInst(Instruction::Shr, N1,
|
|
|
|
Op1, Src->getName()), CI);
|
|
|
|
return new CastInst(N1, CI.getType());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2006-02-27 02:38:23 +00:00
|
|
|
case Instruction::SetEQ:
|
2005-05-04 19:10:26 +00:00
|
|
|
case Instruction::SetNE:
|
2006-02-27 02:38:23 +00:00
|
|
|
// We if we are just checking for a seteq of a single bit and casting it
|
|
|
|
// to an integer. If so, shift the bit to the appropriate place then
|
|
|
|
// cast to integer to avoid the comparison.
|
2005-05-04 19:10:26 +00:00
|
|
|
if (ConstantInt *Op1C = dyn_cast<ConstantInt>(Op1)) {
|
2006-02-27 02:38:23 +00:00
|
|
|
uint64_t Op1CV = Op1C->getZExtValue();
|
|
|
|
// cast (X == 0) to int --> X^1 iff X has only the low bit set.
|
|
|
|
// cast (X == 0) to int --> (X>>1)^1 iff X has only the 2nd bit set.
|
|
|
|
// cast (X == 1) to int --> X iff X has only the low bit set.
|
|
|
|
// cast (X == 2) to int --> X>>1 iff X has only the 2nd bit set.
|
|
|
|
// cast (X != 0) to int --> X iff X has only the low bit set.
|
|
|
|
// cast (X != 0) to int --> X>>1 iff X has only the 2nd bit set.
|
|
|
|
// cast (X != 1) to int --> X^1 iff X has only the low bit set.
|
|
|
|
// cast (X != 2) to int --> (X>>1)^1 iff X has only the 2nd bit set.
|
|
|
|
if (Op1CV == 0 || isPowerOf2_64(Op1CV)) {
|
|
|
|
// If Op1C some other power of two, convert:
|
|
|
|
uint64_t KnownZero, KnownOne;
|
|
|
|
uint64_t TypeMask = Op1->getType()->getIntegralTypeMask();
|
|
|
|
ComputeMaskedBits(Op0, TypeMask, KnownZero, KnownOne);
|
|
|
|
|
|
|
|
if (isPowerOf2_64(KnownZero^TypeMask)) { // Exactly one possible 1?
|
|
|
|
bool isSetNE = SrcI->getOpcode() == Instruction::SetNE;
|
|
|
|
if (Op1CV && (Op1CV != (KnownZero^TypeMask))) {
|
|
|
|
// (X&4) == 2 --> false
|
|
|
|
// (X&4) != 2 --> true
|
2006-02-28 19:47:20 +00:00
|
|
|
Constant *Res = ConstantBool::get(isSetNE);
|
|
|
|
Res = ConstantExpr::getCast(Res, CI.getType());
|
|
|
|
return ReplaceInstUsesWith(CI, Res);
|
2006-02-27 02:38:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
unsigned ShiftAmt = Log2_64(KnownZero^TypeMask);
|
|
|
|
Value *In = Op0;
|
|
|
|
if (ShiftAmt) {
|
2005-05-06 01:53:19 +00:00
|
|
|
// Perform an unsigned shr by shiftamt. Convert input to
|
|
|
|
// unsigned if it is signed.
|
|
|
|
if (In->getType()->isSigned())
|
|
|
|
In = InsertNewInstBefore(new CastInst(In,
|
|
|
|
In->getType()->getUnsignedVersion(), In->getName()),CI);
|
|
|
|
// Insert the shift to put the result in the low bit.
|
|
|
|
In = InsertNewInstBefore(new ShiftInst(Instruction::Shr, In,
|
2006-02-27 02:38:23 +00:00
|
|
|
ConstantInt::get(Type::UByteTy, ShiftAmt),
|
|
|
|
In->getName()+".lobit"), CI);
|
2005-05-06 01:53:19 +00:00
|
|
|
}
|
2006-02-27 02:38:23 +00:00
|
|
|
|
|
|
|
if ((Op1CV != 0) == isSetNE) { // Toggle the low bit.
|
|
|
|
Constant *One = ConstantInt::get(In->getType(), 1);
|
|
|
|
In = BinaryOperator::createXor(In, One, "tmp");
|
|
|
|
InsertNewInstBefore(cast<Instruction>(In), CI);
|
2005-05-06 01:53:19 +00:00
|
|
|
}
|
2006-02-27 02:38:23 +00:00
|
|
|
|
|
|
|
if (CI.getType() == In->getType())
|
|
|
|
return ReplaceInstUsesWith(CI, In);
|
|
|
|
else
|
|
|
|
return new CastInst(In, CI.getType());
|
2005-05-06 01:53:19 +00:00
|
|
|
}
|
2005-05-04 19:10:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2003-07-24 17:35:25 +00:00
|
|
|
}
|
|
|
|
}
|
2005-10-27 05:53:56 +00:00
|
|
|
|
2002-04-18 17:39:14 +00:00
|
|
|
return 0;
|
2001-12-14 16:52:21 +00:00
|
|
|
}
|
|
|
|
|
Implement select.ll:test12*
This transforms code like this:
%C = or %A, %B
%D = select %cond, %C, %A
into:
%C = select %cond, %B, 0
%D = or %A, %C
Since B is often a constant, the select can often be eliminated. In any case,
this reduces the usage count of A, allowing subsequent optimizations to happen.
This xform applies when the operator is any of:
add, sub, mul, or, xor, and, shl, shr
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@12800 91177308-0d34-0410-b5e6-96231b3b80d8
2004-04-09 23:46:01 +00:00
|
|
|
/// GetSelectFoldableOperands - We want to turn code that looks like this:
|
|
|
|
/// %C = or %A, %B
|
|
|
|
/// %D = select %cond, %C, %A
|
|
|
|
/// into:
|
|
|
|
/// %C = select %cond, %B, 0
|
|
|
|
/// %D = or %A, %C
|
|
|
|
///
|
|
|
|
/// Assuming that the specified instruction is an operand to the select, return
|
|
|
|
/// a bitmask indicating which operands of this instruction are foldable if they
|
|
|
|
/// equal the other incoming value of the select.
|
|
|
|
///
|
|
|
|
static unsigned GetSelectFoldableOperands(Instruction *I) {
|
|
|
|
switch (I->getOpcode()) {
|
|
|
|
case Instruction::Add:
|
|
|
|
case Instruction::Mul:
|
|
|
|
case Instruction::And:
|
|
|
|
case Instruction::Or:
|
|
|
|
case Instruction::Xor:
|
|
|
|
return 3; // Can fold through either operand.
|
|
|
|
case Instruction::Sub: // Can only fold on the amount subtracted.
|
|
|
|
case Instruction::Shl: // Can only fold on the shift amount.
|
|
|
|
case Instruction::Shr:
|
2005-04-21 23:48:37 +00:00
|
|
|
return 1;
|
Implement select.ll:test12*
This transforms code like this:
%C = or %A, %B
%D = select %cond, %C, %A
into:
%C = select %cond, %B, 0
%D = or %A, %C
Since B is often a constant, the select can often be eliminated. In any case,
this reduces the usage count of A, allowing subsequent optimizations to happen.
This xform applies when the operator is any of:
add, sub, mul, or, xor, and, shl, shr
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@12800 91177308-0d34-0410-b5e6-96231b3b80d8
2004-04-09 23:46:01 +00:00
|
|
|
default:
|
|
|
|
return 0; // Cannot fold
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// GetSelectFoldableConstant - For the same transformation as the previous
|
|
|
|
/// function, return the identity constant that goes into the select.
|
|
|
|
static Constant *GetSelectFoldableConstant(Instruction *I) {
|
|
|
|
switch (I->getOpcode()) {
|
|
|
|
default: assert(0 && "This cannot happen!"); abort();
|
|
|
|
case Instruction::Add:
|
|
|
|
case Instruction::Sub:
|
|
|
|
case Instruction::Or:
|
|
|
|
case Instruction::Xor:
|
|
|
|
return Constant::getNullValue(I->getType());
|
|
|
|
case Instruction::Shl:
|
|
|
|
case Instruction::Shr:
|
|
|
|
return Constant::getNullValue(Type::UByteTy);
|
|
|
|
case Instruction::And:
|
|
|
|
return ConstantInt::getAllOnesValue(I->getType());
|
|
|
|
case Instruction::Mul:
|
|
|
|
return ConstantInt::get(I->getType(), 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-01-19 21:50:18 +00:00
|
|
|
/// FoldSelectOpOp - Here we have (select c, TI, FI), and we know that TI and FI
|
|
|
|
/// have the same opcode and only one use each. Try to simplify this.
|
|
|
|
Instruction *InstCombiner::FoldSelectOpOp(SelectInst &SI, Instruction *TI,
|
|
|
|
Instruction *FI) {
|
|
|
|
if (TI->getNumOperands() == 1) {
|
|
|
|
// If this is a non-volatile load or a cast from the same type,
|
|
|
|
// merge.
|
|
|
|
if (TI->getOpcode() == Instruction::Cast) {
|
|
|
|
if (TI->getOperand(0)->getType() != FI->getOperand(0)->getType())
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
return 0; // unknown unary op.
|
|
|
|
}
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2005-01-19 21:50:18 +00:00
|
|
|
// Fold this by inserting a select from the input values.
|
|
|
|
SelectInst *NewSI = new SelectInst(SI.getCondition(), TI->getOperand(0),
|
|
|
|
FI->getOperand(0), SI.getName()+".v");
|
|
|
|
InsertNewInstBefore(NewSI, SI);
|
|
|
|
return new CastInst(NewSI, TI->getType());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Only handle binary operators here.
|
|
|
|
if (!isa<ShiftInst>(TI) && !isa<BinaryOperator>(TI))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
// Figure out if the operations have any operands in common.
|
|
|
|
Value *MatchOp, *OtherOpT, *OtherOpF;
|
|
|
|
bool MatchIsOpZero;
|
|
|
|
if (TI->getOperand(0) == FI->getOperand(0)) {
|
|
|
|
MatchOp = TI->getOperand(0);
|
|
|
|
OtherOpT = TI->getOperand(1);
|
|
|
|
OtherOpF = FI->getOperand(1);
|
|
|
|
MatchIsOpZero = true;
|
|
|
|
} else if (TI->getOperand(1) == FI->getOperand(1)) {
|
|
|
|
MatchOp = TI->getOperand(1);
|
|
|
|
OtherOpT = TI->getOperand(0);
|
|
|
|
OtherOpF = FI->getOperand(0);
|
|
|
|
MatchIsOpZero = false;
|
|
|
|
} else if (!TI->isCommutative()) {
|
|
|
|
return 0;
|
|
|
|
} else if (TI->getOperand(0) == FI->getOperand(1)) {
|
|
|
|
MatchOp = TI->getOperand(0);
|
|
|
|
OtherOpT = TI->getOperand(1);
|
|
|
|
OtherOpF = FI->getOperand(0);
|
|
|
|
MatchIsOpZero = true;
|
|
|
|
} else if (TI->getOperand(1) == FI->getOperand(0)) {
|
|
|
|
MatchOp = TI->getOperand(1);
|
|
|
|
OtherOpT = TI->getOperand(0);
|
|
|
|
OtherOpF = FI->getOperand(1);
|
|
|
|
MatchIsOpZero = true;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we reach here, they do have operations in common.
|
|
|
|
SelectInst *NewSI = new SelectInst(SI.getCondition(), OtherOpT,
|
|
|
|
OtherOpF, SI.getName()+".v");
|
|
|
|
InsertNewInstBefore(NewSI, SI);
|
|
|
|
|
|
|
|
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(TI)) {
|
|
|
|
if (MatchIsOpZero)
|
|
|
|
return BinaryOperator::create(BO->getOpcode(), MatchOp, NewSI);
|
|
|
|
else
|
|
|
|
return BinaryOperator::create(BO->getOpcode(), NewSI, MatchOp);
|
|
|
|
} else {
|
|
|
|
if (MatchIsOpZero)
|
|
|
|
return new ShiftInst(cast<ShiftInst>(TI)->getOpcode(), MatchOp, NewSI);
|
|
|
|
else
|
|
|
|
return new ShiftInst(cast<ShiftInst>(TI)->getOpcode(), NewSI, MatchOp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-03-12 05:52:32 +00:00
|
|
|
Instruction *InstCombiner::visitSelectInst(SelectInst &SI) {
|
2004-03-30 19:37:13 +00:00
|
|
|
Value *CondVal = SI.getCondition();
|
|
|
|
Value *TrueVal = SI.getTrueValue();
|
|
|
|
Value *FalseVal = SI.getFalseValue();
|
|
|
|
|
|
|
|
// select true, X, Y -> X
|
|
|
|
// select false, X, Y -> Y
|
|
|
|
if (ConstantBool *C = dyn_cast<ConstantBool>(CondVal))
|
2004-03-12 05:52:32 +00:00
|
|
|
if (C == ConstantBool::True)
|
2004-03-30 19:37:13 +00:00
|
|
|
return ReplaceInstUsesWith(SI, TrueVal);
|
2004-03-12 05:52:32 +00:00
|
|
|
else {
|
|
|
|
assert(C == ConstantBool::False);
|
2004-03-30 19:37:13 +00:00
|
|
|
return ReplaceInstUsesWith(SI, FalseVal);
|
|
|
|
}
|
|
|
|
|
|
|
|
// select C, X, X -> X
|
|
|
|
if (TrueVal == FalseVal)
|
|
|
|
return ReplaceInstUsesWith(SI, TrueVal);
|
|
|
|
|
2004-10-16 18:11:37 +00:00
|
|
|
if (isa<UndefValue>(TrueVal)) // select C, undef, X -> X
|
|
|
|
return ReplaceInstUsesWith(SI, FalseVal);
|
|
|
|
if (isa<UndefValue>(FalseVal)) // select C, X, undef -> X
|
|
|
|
return ReplaceInstUsesWith(SI, TrueVal);
|
|
|
|
if (isa<UndefValue>(CondVal)) { // select undef, X, Y -> X or Y
|
|
|
|
if (isa<Constant>(TrueVal))
|
|
|
|
return ReplaceInstUsesWith(SI, TrueVal);
|
|
|
|
else
|
|
|
|
return ReplaceInstUsesWith(SI, FalseVal);
|
|
|
|
}
|
|
|
|
|
2004-04-08 04:43:23 +00:00
|
|
|
if (SI.getType() == Type::BoolTy)
|
|
|
|
if (ConstantBool *C = dyn_cast<ConstantBool>(TrueVal)) {
|
|
|
|
if (C == ConstantBool::True) {
|
|
|
|
// Change: A = select B, true, C --> A = or B, C
|
2004-06-10 02:07:29 +00:00
|
|
|
return BinaryOperator::createOr(CondVal, FalseVal);
|
2004-04-08 04:43:23 +00:00
|
|
|
} else {
|
|
|
|
// Change: A = select B, false, C --> A = and !B, C
|
|
|
|
Value *NotCond =
|
|
|
|
InsertNewInstBefore(BinaryOperator::createNot(CondVal,
|
|
|
|
"not."+CondVal->getName()), SI);
|
2004-06-10 02:07:29 +00:00
|
|
|
return BinaryOperator::createAnd(NotCond, FalseVal);
|
2004-04-08 04:43:23 +00:00
|
|
|
}
|
|
|
|
} else if (ConstantBool *C = dyn_cast<ConstantBool>(FalseVal)) {
|
|
|
|
if (C == ConstantBool::False) {
|
|
|
|
// Change: A = select B, C, false --> A = and B, C
|
2004-06-10 02:07:29 +00:00
|
|
|
return BinaryOperator::createAnd(CondVal, TrueVal);
|
2004-04-08 04:43:23 +00:00
|
|
|
} else {
|
|
|
|
// Change: A = select B, C, true --> A = or !B, C
|
|
|
|
Value *NotCond =
|
|
|
|
InsertNewInstBefore(BinaryOperator::createNot(CondVal,
|
|
|
|
"not."+CondVal->getName()), SI);
|
2004-06-10 02:07:29 +00:00
|
|
|
return BinaryOperator::createOr(NotCond, TrueVal);
|
2004-04-08 04:43:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-04-09 19:05:30 +00:00
|
|
|
// Selecting between two integer constants?
|
|
|
|
if (ConstantInt *TrueValC = dyn_cast<ConstantInt>(TrueVal))
|
|
|
|
if (ConstantInt *FalseValC = dyn_cast<ConstantInt>(FalseVal)) {
|
|
|
|
// select C, 1, 0 -> cast C to int
|
|
|
|
if (FalseValC->isNullValue() && TrueValC->getRawValue() == 1) {
|
|
|
|
return new CastInst(CondVal, SI.getType());
|
|
|
|
} else if (TrueValC->isNullValue() && FalseValC->getRawValue() == 1) {
|
|
|
|
// select C, 0, 1 -> cast !C to int
|
|
|
|
Value *NotCond =
|
|
|
|
InsertNewInstBefore(BinaryOperator::createNot(CondVal,
|
2004-04-09 18:19:44 +00:00
|
|
|
"not."+CondVal->getName()), SI);
|
2004-04-09 19:05:30 +00:00
|
|
|
return new CastInst(NotCond, SI.getType());
|
2004-04-09 18:19:44 +00:00
|
|
|
}
|
2004-06-09 07:59:58 +00:00
|
|
|
|
|
|
|
// If one of the constants is zero (we know they can't both be) and we
|
|
|
|
// have a setcc instruction with zero, and we have an 'and' with the
|
|
|
|
// non-constant value, eliminate this whole mess. This corresponds to
|
|
|
|
// cases like this: ((X & 27) ? 27 : 0)
|
|
|
|
if (TrueValC->isNullValue() || FalseValC->isNullValue())
|
|
|
|
if (Instruction *IC = dyn_cast<Instruction>(SI.getCondition()))
|
|
|
|
if ((IC->getOpcode() == Instruction::SetEQ ||
|
|
|
|
IC->getOpcode() == Instruction::SetNE) &&
|
|
|
|
isa<ConstantInt>(IC->getOperand(1)) &&
|
|
|
|
cast<Constant>(IC->getOperand(1))->isNullValue())
|
|
|
|
if (Instruction *ICA = dyn_cast<Instruction>(IC->getOperand(0)))
|
|
|
|
if (ICA->getOpcode() == Instruction::And &&
|
2005-04-21 23:48:37 +00:00
|
|
|
isa<ConstantInt>(ICA->getOperand(1)) &&
|
|
|
|
(ICA->getOperand(1) == TrueValC ||
|
|
|
|
ICA->getOperand(1) == FalseValC) &&
|
2004-06-09 07:59:58 +00:00
|
|
|
isOneBitSet(cast<ConstantInt>(ICA->getOperand(1)))) {
|
|
|
|
// Okay, now we know that everything is set up, we just don't
|
|
|
|
// know whether we have a setne or seteq and whether the true or
|
|
|
|
// false val is the zero.
|
|
|
|
bool ShouldNotVal = !TrueValC->isNullValue();
|
|
|
|
ShouldNotVal ^= IC->getOpcode() == Instruction::SetNE;
|
|
|
|
Value *V = ICA;
|
|
|
|
if (ShouldNotVal)
|
|
|
|
V = InsertNewInstBefore(BinaryOperator::create(
|
|
|
|
Instruction::Xor, V, ICA->getOperand(1)), SI);
|
|
|
|
return ReplaceInstUsesWith(SI, V);
|
|
|
|
}
|
2004-03-12 05:52:32 +00:00
|
|
|
}
|
2004-04-10 22:21:27 +00:00
|
|
|
|
|
|
|
// See if we are selecting two values based on a comparison of the two values.
|
|
|
|
if (SetCondInst *SCI = dyn_cast<SetCondInst>(CondVal)) {
|
|
|
|
if (SCI->getOperand(0) == TrueVal && SCI->getOperand(1) == FalseVal) {
|
|
|
|
// Transform (X == Y) ? X : Y -> Y
|
|
|
|
if (SCI->getOpcode() == Instruction::SetEQ)
|
|
|
|
return ReplaceInstUsesWith(SI, FalseVal);
|
|
|
|
// Transform (X != Y) ? X : Y -> X
|
|
|
|
if (SCI->getOpcode() == Instruction::SetNE)
|
|
|
|
return ReplaceInstUsesWith(SI, TrueVal);
|
|
|
|
// NOTE: if we wanted to, this is where to detect MIN/MAX/ABS/etc.
|
|
|
|
|
|
|
|
} else if (SCI->getOperand(0) == FalseVal && SCI->getOperand(1) == TrueVal){
|
|
|
|
// Transform (X == Y) ? Y : X -> X
|
|
|
|
if (SCI->getOpcode() == Instruction::SetEQ)
|
2004-04-11 01:39:19 +00:00
|
|
|
return ReplaceInstUsesWith(SI, FalseVal);
|
2004-04-10 22:21:27 +00:00
|
|
|
// Transform (X != Y) ? Y : X -> Y
|
|
|
|
if (SCI->getOpcode() == Instruction::SetNE)
|
2004-04-11 01:39:19 +00:00
|
|
|
return ReplaceInstUsesWith(SI, TrueVal);
|
2004-04-10 22:21:27 +00:00
|
|
|
// NOTE: if we wanted to, this is where to detect MIN/MAX/ABS/etc.
|
|
|
|
}
|
|
|
|
}
|
2005-04-21 23:48:37 +00:00
|
|
|
|
Turn select C, (X+Y), (X-Y) --> (X+(select C, Y, (-Y))). This occurs in
the 'sim' program and probably elsewhere. In sim, it comes up for cases
like this:
#define round(x) ((x)>0.0 ? (x)+0.5 : (x)-0.5)
double G;
void T(double X) { G = round(X); }
(it uses the round macro a lot). This changes the LLVM code from:
%tmp.1 = setgt double %X, 0.000000e+00 ; <bool> [#uses=1]
%tmp.4 = add double %X, 5.000000e-01 ; <double> [#uses=1]
%tmp.6 = sub double %X, 5.000000e-01 ; <double> [#uses=1]
%mem_tmp.0 = select bool %tmp.1, double %tmp.4, double %tmp.6
store double %mem_tmp.0, double* %G
to:
%tmp.1 = setgt double %X, 0.000000e+00 ; <bool> [#uses=1]
%mem_tmp.0.p = select bool %tmp.1, double 5.000000e-01, double -5.000000e-01
%mem_tmp.0 = add double %mem_tmp.0.p, %X
store double %mem_tmp.0, double* %G
ret void
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@19537 91177308-0d34-0410-b5e6-96231b3b80d8
2005-01-13 22:52:24 +00:00
|
|
|
if (Instruction *TI = dyn_cast<Instruction>(TrueVal))
|
|
|
|
if (Instruction *FI = dyn_cast<Instruction>(FalseVal))
|
|
|
|
if (TI->hasOneUse() && FI->hasOneUse()) {
|
|
|
|
bool isInverse = false;
|
|
|
|
Instruction *AddOp = 0, *SubOp = 0;
|
|
|
|
|
2005-01-19 21:50:18 +00:00
|
|
|
// Turn (select C, (op X, Y), (op X, Z)) -> (op X, (select C, Y, Z))
|
|
|
|
if (TI->getOpcode() == FI->getOpcode())
|
|
|
|
if (Instruction *IV = FoldSelectOpOp(SI, TI, FI))
|
|
|
|
return IV;
|
|
|
|
|
|
|
|
// Turn select C, (X+Y), (X-Y) --> (X+(select C, Y, (-Y))). This is
|
|
|
|
// even legal for FP.
|
Turn select C, (X+Y), (X-Y) --> (X+(select C, Y, (-Y))). This occurs in
the 'sim' program and probably elsewhere. In sim, it comes up for cases
like this:
#define round(x) ((x)>0.0 ? (x)+0.5 : (x)-0.5)
double G;
void T(double X) { G = round(X); }
(it uses the round macro a lot). This changes the LLVM code from:
%tmp.1 = setgt double %X, 0.000000e+00 ; <bool> [#uses=1]
%tmp.4 = add double %X, 5.000000e-01 ; <double> [#uses=1]
%tmp.6 = sub double %X, 5.000000e-01 ; <double> [#uses=1]
%mem_tmp.0 = select bool %tmp.1, double %tmp.4, double %tmp.6
store double %mem_tmp.0, double* %G
to:
%tmp.1 = setgt double %X, 0.000000e+00 ; <bool> [#uses=1]
%mem_tmp.0.p = select bool %tmp.1, double 5.000000e-01, double -5.000000e-01
%mem_tmp.0 = add double %mem_tmp.0.p, %X
store double %mem_tmp.0, double* %G
ret void
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@19537 91177308-0d34-0410-b5e6-96231b3b80d8
2005-01-13 22:52:24 +00:00
|
|
|
if (TI->getOpcode() == Instruction::Sub &&
|
|
|
|
FI->getOpcode() == Instruction::Add) {
|
|
|
|
AddOp = FI; SubOp = TI;
|
|
|
|
} else if (FI->getOpcode() == Instruction::Sub &&
|
|
|
|
TI->getOpcode() == Instruction::Add) {
|
|
|
|
AddOp = TI; SubOp = FI;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (AddOp) {
|
|
|
|
Value *OtherAddOp = 0;
|
|
|
|
if (SubOp->getOperand(0) == AddOp->getOperand(0)) {
|
|
|
|
OtherAddOp = AddOp->getOperand(1);
|
|
|
|
} else if (SubOp->getOperand(0) == AddOp->getOperand(1)) {
|
|
|
|
OtherAddOp = AddOp->getOperand(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (OtherAddOp) {
|
Fix a problem that Nate noticed that boils down to an over conservative check
in the code that does "select C, (X+Y), (X-Y) --> (X+(select C, Y, (-Y)))".
We now compile this loop:
LBB1_1: ; no_exit
add r6, r2, r3
subf r3, r2, r3
cmpwi cr0, r2, 0
addi r7, r5, 4
lwz r2, 0(r5)
addi r4, r4, 1
blt cr0, LBB1_4 ; no_exit
LBB1_3: ; no_exit
mr r3, r6
LBB1_4: ; no_exit
cmpwi cr0, r4, 16
mr r5, r7
bne cr0, LBB1_1 ; no_exit
into this instead:
LBB1_1: ; no_exit
srawi r6, r2, 31
add r2, r2, r6
xor r6, r2, r6
addi r7, r5, 4
lwz r2, 0(r5)
addi r4, r4, 1
add r3, r3, r6
cmpwi cr0, r4, 16
mr r5, r7
bne cr0, LBB1_1 ; no_exit
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@26356 91177308-0d34-0410-b5e6-96231b3b80d8
2006-02-24 18:05:58 +00:00
|
|
|
// So at this point we know we have (Y -> OtherAddOp):
|
|
|
|
// select C, (add X, Y), (sub X, Z)
|
|
|
|
Value *NegVal; // Compute -Z
|
|
|
|
if (Constant *C = dyn_cast<Constant>(SubOp->getOperand(1))) {
|
|
|
|
NegVal = ConstantExpr::getNeg(C);
|
|
|
|
} else {
|
|
|
|
NegVal = InsertNewInstBefore(
|
|
|
|
BinaryOperator::createNeg(SubOp->getOperand(1), "tmp"), SI);
|
|
|
|
}
|
Turn select C, (X+Y), (X-Y) --> (X+(select C, Y, (-Y))). This occurs in
the 'sim' program and probably elsewhere. In sim, it comes up for cases
like this:
#define round(x) ((x)>0.0 ? (x)+0.5 : (x)-0.5)
double G;
void T(double X) { G = round(X); }
(it uses the round macro a lot). This changes the LLVM code from:
%tmp.1 = setgt double %X, 0.000000e+00 ; <bool> [#uses=1]
%tmp.4 = add double %X, 5.000000e-01 ; <double> [#uses=1]
%tmp.6 = sub double %X, 5.000000e-01 ; <double> [#uses=1]
%mem_tmp.0 = select bool %tmp.1, double %tmp.4, double %tmp.6
store double %mem_tmp.0, double* %G
to:
%tmp.1 = setgt double %X, 0.000000e+00 ; <bool> [#uses=1]
%mem_tmp.0.p = select bool %tmp.1, double 5.000000e-01, double -5.000000e-01
%mem_tmp.0 = add double %mem_tmp.0.p, %X
store double %mem_tmp.0, double* %G
ret void
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@19537 91177308-0d34-0410-b5e6-96231b3b80d8
2005-01-13 22:52:24 +00:00
|
|
|
|
Fix a problem that Nate noticed that boils down to an over conservative check
in the code that does "select C, (X+Y), (X-Y) --> (X+(select C, Y, (-Y)))".
We now compile this loop:
LBB1_1: ; no_exit
add r6, r2, r3
subf r3, r2, r3
cmpwi cr0, r2, 0
addi r7, r5, 4
lwz r2, 0(r5)
addi r4, r4, 1
blt cr0, LBB1_4 ; no_exit
LBB1_3: ; no_exit
mr r3, r6
LBB1_4: ; no_exit
cmpwi cr0, r4, 16
mr r5, r7
bne cr0, LBB1_1 ; no_exit
into this instead:
LBB1_1: ; no_exit
srawi r6, r2, 31
add r2, r2, r6
xor r6, r2, r6
addi r7, r5, 4
lwz r2, 0(r5)
addi r4, r4, 1
add r3, r3, r6
cmpwi cr0, r4, 16
mr r5, r7
bne cr0, LBB1_1 ; no_exit
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@26356 91177308-0d34-0410-b5e6-96231b3b80d8
2006-02-24 18:05:58 +00:00
|
|
|
Value *NewTrueOp = OtherAddOp;
|
|
|
|
Value *NewFalseOp = NegVal;
|
|
|
|
if (AddOp != TI)
|
|
|
|
std::swap(NewTrueOp, NewFalseOp);
|
|
|
|
Instruction *NewSel =
|
|
|
|
new SelectInst(CondVal, NewTrueOp,NewFalseOp,SI.getName()+".p");
|
2005-04-21 23:48:37 +00:00
|
|
|
|
Fix a problem that Nate noticed that boils down to an over conservative check
in the code that does "select C, (X+Y), (X-Y) --> (X+(select C, Y, (-Y)))".
We now compile this loop:
LBB1_1: ; no_exit
add r6, r2, r3
subf r3, r2, r3
cmpwi cr0, r2, 0
addi r7, r5, 4
lwz r2, 0(r5)
addi r4, r4, 1
blt cr0, LBB1_4 ; no_exit
LBB1_3: ; no_exit
mr r3, r6
LBB1_4: ; no_exit
cmpwi cr0, r4, 16
mr r5, r7
bne cr0, LBB1_1 ; no_exit
into this instead:
LBB1_1: ; no_exit
srawi r6, r2, 31
add r2, r2, r6
xor r6, r2, r6
addi r7, r5, 4
lwz r2, 0(r5)
addi r4, r4, 1
add r3, r3, r6
cmpwi cr0, r4, 16
mr r5, r7
bne cr0, LBB1_1 ; no_exit
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@26356 91177308-0d34-0410-b5e6-96231b3b80d8
2006-02-24 18:05:58 +00:00
|
|
|
NewSel = InsertNewInstBefore(NewSel, SI);
|
|
|
|
return BinaryOperator::createAdd(SubOp->getOperand(0), NewSel);
|
Turn select C, (X+Y), (X-Y) --> (X+(select C, Y, (-Y))). This occurs in
the 'sim' program and probably elsewhere. In sim, it comes up for cases
like this:
#define round(x) ((x)>0.0 ? (x)+0.5 : (x)-0.5)
double G;
void T(double X) { G = round(X); }
(it uses the round macro a lot). This changes the LLVM code from:
%tmp.1 = setgt double %X, 0.000000e+00 ; <bool> [#uses=1]
%tmp.4 = add double %X, 5.000000e-01 ; <double> [#uses=1]
%tmp.6 = sub double %X, 5.000000e-01 ; <double> [#uses=1]
%mem_tmp.0 = select bool %tmp.1, double %tmp.4, double %tmp.6
store double %mem_tmp.0, double* %G
to:
%tmp.1 = setgt double %X, 0.000000e+00 ; <bool> [#uses=1]
%mem_tmp.0.p = select bool %tmp.1, double 5.000000e-01, double -5.000000e-01
%mem_tmp.0 = add double %mem_tmp.0.p, %X
store double %mem_tmp.0, double* %G
ret void
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@19537 91177308-0d34-0410-b5e6-96231b3b80d8
2005-01-13 22:52:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2005-04-21 23:48:37 +00:00
|
|
|
|
Implement select.ll:test12*
This transforms code like this:
%C = or %A, %B
%D = select %cond, %C, %A
into:
%C = select %cond, %B, 0
%D = or %A, %C
Since B is often a constant, the select can often be eliminated. In any case,
this reduces the usage count of A, allowing subsequent optimizations to happen.
This xform applies when the operator is any of:
add, sub, mul, or, xor, and, shl, shr
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@12800 91177308-0d34-0410-b5e6-96231b3b80d8
2004-04-09 23:46:01 +00:00
|
|
|
// See if we can fold the select into one of our operands.
|
|
|
|
if (SI.getType()->isInteger()) {
|
|
|
|
// See the comment above GetSelectFoldableOperands for a description of the
|
|
|
|
// transformation we are doing here.
|
|
|
|
if (Instruction *TVI = dyn_cast<Instruction>(TrueVal))
|
|
|
|
if (TVI->hasOneUse() && TVI->getNumOperands() == 2 &&
|
|
|
|
!isa<Constant>(FalseVal))
|
|
|
|
if (unsigned SFO = GetSelectFoldableOperands(TVI)) {
|
|
|
|
unsigned OpToFold = 0;
|
|
|
|
if ((SFO & 1) && FalseVal == TVI->getOperand(0)) {
|
|
|
|
OpToFold = 1;
|
|
|
|
} else if ((SFO & 2) && FalseVal == TVI->getOperand(1)) {
|
|
|
|
OpToFold = 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (OpToFold) {
|
|
|
|
Constant *C = GetSelectFoldableConstant(TVI);
|
|
|
|
std::string Name = TVI->getName(); TVI->setName("");
|
|
|
|
Instruction *NewSel =
|
|
|
|
new SelectInst(SI.getCondition(), TVI->getOperand(2-OpToFold), C,
|
|
|
|
Name);
|
|
|
|
InsertNewInstBefore(NewSel, SI);
|
|
|
|
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(TVI))
|
|
|
|
return BinaryOperator::create(BO->getOpcode(), FalseVal, NewSel);
|
|
|
|
else if (ShiftInst *SI = dyn_cast<ShiftInst>(TVI))
|
|
|
|
return new ShiftInst(SI->getOpcode(), FalseVal, NewSel);
|
|
|
|
else {
|
|
|
|
assert(0 && "Unknown instruction!!");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-09-29 17:40:11 +00:00
|
|
|
|
Implement select.ll:test12*
This transforms code like this:
%C = or %A, %B
%D = select %cond, %C, %A
into:
%C = select %cond, %B, 0
%D = or %A, %C
Since B is often a constant, the select can often be eliminated. In any case,
this reduces the usage count of A, allowing subsequent optimizations to happen.
This xform applies when the operator is any of:
add, sub, mul, or, xor, and, shl, shr
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@12800 91177308-0d34-0410-b5e6-96231b3b80d8
2004-04-09 23:46:01 +00:00
|
|
|
if (Instruction *FVI = dyn_cast<Instruction>(FalseVal))
|
|
|
|
if (FVI->hasOneUse() && FVI->getNumOperands() == 2 &&
|
|
|
|
!isa<Constant>(TrueVal))
|
|
|
|
if (unsigned SFO = GetSelectFoldableOperands(FVI)) {
|
|
|
|
unsigned OpToFold = 0;
|
|
|
|
if ((SFO & 1) && TrueVal == FVI->getOperand(0)) {
|
|
|
|
OpToFold = 1;
|
|
|
|
} else if ((SFO & 2) && TrueVal == FVI->getOperand(1)) {
|
|
|
|
OpToFold = 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (OpToFold) {
|
|
|
|
Constant *C = GetSelectFoldableConstant(FVI);
|
|
|
|
std::string Name = FVI->getName(); FVI->setName("");
|
|
|
|
Instruction *NewSel =
|
|
|
|
new SelectInst(SI.getCondition(), C, FVI->getOperand(2-OpToFold),
|
|
|
|
Name);
|
|
|
|
InsertNewInstBefore(NewSel, SI);
|
|
|
|
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(FVI))
|
|
|
|
return BinaryOperator::create(BO->getOpcode(), TrueVal, NewSel);
|
|
|
|
else if (ShiftInst *SI = dyn_cast<ShiftInst>(FVI))
|
|
|
|
return new ShiftInst(SI->getOpcode(), TrueVal, NewSel);
|
|
|
|
else {
|
|
|
|
assert(0 && "Unknown instruction!!");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2005-04-24 07:30:14 +00:00
|
|
|
|
|
|
|
if (BinaryOperator::isNot(CondVal)) {
|
|
|
|
SI.setOperand(0, BinaryOperator::getNotArgument(CondVal));
|
|
|
|
SI.setOperand(1, FalseVal);
|
|
|
|
SI.setOperand(2, TrueVal);
|
|
|
|
return &SI;
|
|
|
|
}
|
|
|
|
|
2004-03-12 05:52:32 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-03-06 20:18:44 +00:00
|
|
|
/// GetKnownAlignment - If the specified pointer has an alignment that we can
|
|
|
|
/// determine, return it, otherwise return 0.
|
|
|
|
static unsigned GetKnownAlignment(Value *V, TargetData *TD) {
|
|
|
|
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V)) {
|
|
|
|
unsigned Align = GV->getAlignment();
|
|
|
|
if (Align == 0 && TD)
|
|
|
|
Align = TD->getTypeAlignment(GV->getType()->getElementType());
|
|
|
|
return Align;
|
|
|
|
} else if (AllocationInst *AI = dyn_cast<AllocationInst>(V)) {
|
|
|
|
unsigned Align = AI->getAlignment();
|
|
|
|
if (Align == 0 && TD) {
|
|
|
|
if (isa<AllocaInst>(AI))
|
|
|
|
Align = TD->getTypeAlignment(AI->getType()->getElementType());
|
|
|
|
else if (isa<MallocInst>(AI)) {
|
|
|
|
// Malloc returns maximally aligned memory.
|
|
|
|
Align = TD->getTypeAlignment(AI->getType()->getElementType());
|
|
|
|
Align = std::max(Align, (unsigned)TD->getTypeAlignment(Type::DoubleTy));
|
|
|
|
Align = std::max(Align, (unsigned)TD->getTypeAlignment(Type::LongTy));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Align;
|
2006-03-07 01:28:57 +00:00
|
|
|
} else if (isa<CastInst>(V) ||
|
|
|
|
(isa<ConstantExpr>(V) &&
|
|
|
|
cast<ConstantExpr>(V)->getOpcode() == Instruction::Cast)) {
|
|
|
|
User *CI = cast<User>(V);
|
2006-03-06 20:18:44 +00:00
|
|
|
if (isa<PointerType>(CI->getOperand(0)->getType()))
|
|
|
|
return GetKnownAlignment(CI->getOperand(0), TD);
|
|
|
|
return 0;
|
2006-03-07 01:28:57 +00:00
|
|
|
} else if (isa<GetElementPtrInst>(V) ||
|
|
|
|
(isa<ConstantExpr>(V) &&
|
|
|
|
cast<ConstantExpr>(V)->getOpcode()==Instruction::GetElementPtr)) {
|
|
|
|
User *GEPI = cast<User>(V);
|
2006-03-06 20:18:44 +00:00
|
|
|
unsigned BaseAlignment = GetKnownAlignment(GEPI->getOperand(0), TD);
|
|
|
|
if (BaseAlignment == 0) return 0;
|
|
|
|
|
|
|
|
// If all indexes are zero, it is just the alignment of the base pointer.
|
|
|
|
bool AllZeroOperands = true;
|
|
|
|
for (unsigned i = 1, e = GEPI->getNumOperands(); i != e; ++i)
|
|
|
|
if (!isa<Constant>(GEPI->getOperand(i)) ||
|
|
|
|
!cast<Constant>(GEPI->getOperand(i))->isNullValue()) {
|
|
|
|
AllZeroOperands = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (AllZeroOperands)
|
|
|
|
return BaseAlignment;
|
|
|
|
|
|
|
|
// Otherwise, if the base alignment is >= the alignment we expect for the
|
|
|
|
// base pointer type, then we know that the resultant pointer is aligned at
|
|
|
|
// least as much as its type requires.
|
|
|
|
if (!TD) return 0;
|
|
|
|
|
|
|
|
const Type *BasePtrTy = GEPI->getOperand(0)->getType();
|
|
|
|
if (TD->getTypeAlignment(cast<PointerType>(BasePtrTy)->getElementType())
|
2006-03-07 01:28:57 +00:00
|
|
|
<= BaseAlignment) {
|
|
|
|
const Type *GEPTy = GEPI->getType();
|
|
|
|
return TD->getTypeAlignment(cast<PointerType>(GEPTy)->getElementType());
|
|
|
|
}
|
2006-03-06 20:18:44 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2004-03-12 05:52:32 +00:00
|
|
|
|
2006-01-13 20:11:04 +00:00
|
|
|
/// visitCallInst - CallInst simplification. This mostly only handles folding
|
|
|
|
/// of intrinsic instructions. For normal calls, it allows visitCallSite to do
|
|
|
|
/// the heavy lifting.
|
|
|
|
///
|
2003-06-19 17:00:31 +00:00
|
|
|
Instruction *InstCombiner::visitCallInst(CallInst &CI) {
|
2006-01-13 20:11:04 +00:00
|
|
|
IntrinsicInst *II = dyn_cast<IntrinsicInst>(&CI);
|
|
|
|
if (!II) return visitCallSite(&CI);
|
|
|
|
|
2004-02-28 05:22:00 +00:00
|
|
|
// Intrinsics cannot occur in an invoke, so handle them here instead of in
|
|
|
|
// visitCallSite.
|
2006-01-13 20:11:04 +00:00
|
|
|
if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(II)) {
|
2004-10-12 04:52:52 +00:00
|
|
|
bool Changed = false;
|
|
|
|
|
|
|
|
// memmove/cpy/set of zero bytes is a noop.
|
|
|
|
if (Constant *NumBytes = dyn_cast<Constant>(MI->getLength())) {
|
|
|
|
if (NumBytes->isNullValue()) return EraseInstFromFunction(CI);
|
|
|
|
|
|
|
|
if (ConstantInt *CI = dyn_cast<ConstantInt>(NumBytes))
|
|
|
|
if (CI->getRawValue() == 1) {
|
|
|
|
// Replace the instruction with just byte operations. We would
|
|
|
|
// transform other cases to loads/stores, but we don't know if
|
|
|
|
// alignment is sufficient.
|
|
|
|
}
|
2004-02-28 05:22:00 +00:00
|
|
|
}
|
|
|
|
|
2004-10-12 04:52:52 +00:00
|
|
|
// If we have a memmove and the source operation is a constant global,
|
|
|
|
// then the source and dest pointers can't alias, so we can change this
|
|
|
|
// into a call to memcpy.
|
2006-03-06 20:18:44 +00:00
|
|
|
if (MemMoveInst *MMI = dyn_cast<MemMoveInst>(II)) {
|
2004-10-12 04:52:52 +00:00
|
|
|
if (GlobalVariable *GVSrc = dyn_cast<GlobalVariable>(MMI->getSource()))
|
|
|
|
if (GVSrc->isConstant()) {
|
|
|
|
Module *M = CI.getParent()->getParent()->getParent();
|
2006-03-03 01:34:17 +00:00
|
|
|
const char *Name;
|
|
|
|
if (CI.getCalledFunction()->getFunctionType()->getParamType(3) ==
|
|
|
|
Type::UIntTy)
|
|
|
|
Name = "llvm.memcpy.i32";
|
|
|
|
else
|
|
|
|
Name = "llvm.memcpy.i64";
|
|
|
|
Function *MemCpy = M->getOrInsertFunction(Name,
|
2004-10-12 04:52:52 +00:00
|
|
|
CI.getCalledFunction()->getFunctionType());
|
|
|
|
CI.setOperand(0, MemCpy);
|
|
|
|
Changed = true;
|
|
|
|
}
|
2006-03-06 20:18:44 +00:00
|
|
|
}
|
2004-10-12 04:52:52 +00:00
|
|
|
|
2006-03-06 20:18:44 +00:00
|
|
|
// If we can determine a pointer alignment that is bigger than currently
|
|
|
|
// set, update the alignment.
|
|
|
|
if (isa<MemCpyInst>(MI) || isa<MemMoveInst>(MI)) {
|
|
|
|
unsigned Alignment1 = GetKnownAlignment(MI->getOperand(1), TD);
|
|
|
|
unsigned Alignment2 = GetKnownAlignment(MI->getOperand(2), TD);
|
|
|
|
unsigned Align = std::min(Alignment1, Alignment2);
|
|
|
|
if (MI->getAlignment()->getRawValue() < Align) {
|
|
|
|
MI->setAlignment(ConstantUInt::get(Type::UIntTy, Align));
|
|
|
|
Changed = true;
|
|
|
|
}
|
|
|
|
} else if (isa<MemSetInst>(MI)) {
|
|
|
|
unsigned Alignment = GetKnownAlignment(MI->getDest(), TD);
|
|
|
|
if (MI->getAlignment()->getRawValue() < Alignment) {
|
|
|
|
MI->setAlignment(ConstantUInt::get(Type::UIntTy, Alignment));
|
|
|
|
Changed = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-01-13 20:11:04 +00:00
|
|
|
if (Changed) return II;
|
2006-01-13 21:28:09 +00:00
|
|
|
} else {
|
|
|
|
switch (II->getIntrinsicID()) {
|
|
|
|
default: break;
|
Turn altivec lvx/stvx intrinsics into loads and stores. This allows the
elimination of one load from this:
int AreSecondAndThirdElementsBothNegative( vector float *in ) {
#define QNaN 0x7FC00000
const vector unsigned int testData = (vector unsigned int)( QNaN, 0, 0, QNaN );
vector float test = vec_ld( 0, (float*) &testData );
return ! vec_any_ge( test, *in );
}
Now generating:
_AreSecondAndThirdElementsBothNegative:
mfspr r2, 256
oris r4, r2, 49152
mtspr 256, r4
li r4, lo16(LCPI1_0)
lis r5, ha16(LCPI1_0)
addi r6, r1, -16
lvx v0, r5, r4
stvx v0, 0, r6
lvx v1, 0, r3
vcmpgefp. v0, v0, v1
mfcr r3, 2
rlwinm r3, r3, 27, 31, 31
xori r3, r3, 1
cntlzw r3, r3
srwi r3, r3, 5
mtspr 256, r2
blr
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@27352 91177308-0d34-0410-b5e6-96231b3b80d8
2006-04-02 05:30:25 +00:00
|
|
|
case Intrinsic::ppc_altivec_lvx:
|
|
|
|
case Intrinsic::ppc_altivec_lvxl:
|
2006-04-17 22:26:56 +00:00
|
|
|
case Intrinsic::x86_sse_loadu_ps:
|
|
|
|
case Intrinsic::x86_sse2_loadu_pd:
|
|
|
|
case Intrinsic::x86_sse2_loadu_dq:
|
|
|
|
// Turn PPC lvx -> load if the pointer is known aligned.
|
|
|
|
// Turn X86 loadups -> load if the pointer is known aligned.
|
Turn altivec lvx/stvx intrinsics into loads and stores. This allows the
elimination of one load from this:
int AreSecondAndThirdElementsBothNegative( vector float *in ) {
#define QNaN 0x7FC00000
const vector unsigned int testData = (vector unsigned int)( QNaN, 0, 0, QNaN );
vector float test = vec_ld( 0, (float*) &testData );
return ! vec_any_ge( test, *in );
}
Now generating:
_AreSecondAndThirdElementsBothNegative:
mfspr r2, 256
oris r4, r2, 49152
mtspr 256, r4
li r4, lo16(LCPI1_0)
lis r5, ha16(LCPI1_0)
addi r6, r1, -16
lvx v0, r5, r4
stvx v0, 0, r6
lvx v1, 0, r3
vcmpgefp. v0, v0, v1
mfcr r3, 2
rlwinm r3, r3, 27, 31, 31
xori r3, r3, 1
cntlzw r3, r3
srwi r3, r3, 5
mtspr 256, r2
blr
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@27352 91177308-0d34-0410-b5e6-96231b3b80d8
2006-04-02 05:30:25 +00:00
|
|
|
if (GetKnownAlignment(II->getOperand(1), TD) >= 16) {
|
Lower vperm(x,y, mask) -> shuffle(x,y,mask) if mask is constant. This allows
us to compile oh-so-realistic stuff like this:
vec_vperm(A, B, (vector unsigned char){14});
to:
vspltb v0, v0, 14
instead of:
vspltisb v0, 14
vperm v0, v2, v1, v0
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@27452 91177308-0d34-0410-b5e6-96231b3b80d8
2006-04-06 19:19:17 +00:00
|
|
|
Value *Ptr = InsertCastBefore(II->getOperand(1),
|
|
|
|
PointerType::get(II->getType()), CI);
|
Turn altivec lvx/stvx intrinsics into loads and stores. This allows the
elimination of one load from this:
int AreSecondAndThirdElementsBothNegative( vector float *in ) {
#define QNaN 0x7FC00000
const vector unsigned int testData = (vector unsigned int)( QNaN, 0, 0, QNaN );
vector float test = vec_ld( 0, (float*) &testData );
return ! vec_any_ge( test, *in );
}
Now generating:
_AreSecondAndThirdElementsBothNegative:
mfspr r2, 256
oris r4, r2, 49152
mtspr 256, r4
li r4, lo16(LCPI1_0)
lis r5, ha16(LCPI1_0)
addi r6, r1, -16
lvx v0, r5, r4
stvx v0, 0, r6
lvx v1, 0, r3
vcmpgefp. v0, v0, v1
mfcr r3, 2
rlwinm r3, r3, 27, 31, 31
xori r3, r3, 1
cntlzw r3, r3
srwi r3, r3, 5
mtspr 256, r2
blr
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@27352 91177308-0d34-0410-b5e6-96231b3b80d8
2006-04-02 05:30:25 +00:00
|
|
|
return new LoadInst(Ptr);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case Intrinsic::ppc_altivec_stvx:
|
|
|
|
case Intrinsic::ppc_altivec_stvxl:
|
|
|
|
// Turn stvx -> store if the pointer is known aligned.
|
|
|
|
if (GetKnownAlignment(II->getOperand(2), TD) >= 16) {
|
Lower vperm(x,y, mask) -> shuffle(x,y,mask) if mask is constant. This allows
us to compile oh-so-realistic stuff like this:
vec_vperm(A, B, (vector unsigned char){14});
to:
vspltb v0, v0, 14
instead of:
vspltisb v0, 14
vperm v0, v2, v1, v0
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@27452 91177308-0d34-0410-b5e6-96231b3b80d8
2006-04-06 19:19:17 +00:00
|
|
|
const Type *OpPtrTy = PointerType::get(II->getOperand(1)->getType());
|
|
|
|
Value *Ptr = InsertCastBefore(II->getOperand(2), OpPtrTy, CI);
|
Turn altivec lvx/stvx intrinsics into loads and stores. This allows the
elimination of one load from this:
int AreSecondAndThirdElementsBothNegative( vector float *in ) {
#define QNaN 0x7FC00000
const vector unsigned int testData = (vector unsigned int)( QNaN, 0, 0, QNaN );
vector float test = vec_ld( 0, (float*) &testData );
return ! vec_any_ge( test, *in );
}
Now generating:
_AreSecondAndThirdElementsBothNegative:
mfspr r2, 256
oris r4, r2, 49152
mtspr 256, r4
li r4, lo16(LCPI1_0)
lis r5, ha16(LCPI1_0)
addi r6, r1, -16
lvx v0, r5, r4
stvx v0, 0, r6
lvx v1, 0, r3
vcmpgefp. v0, v0, v1
mfcr r3, 2
rlwinm r3, r3, 27, 31, 31
xori r3, r3, 1
cntlzw r3, r3
srwi r3, r3, 5
mtspr 256, r2
blr
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@27352 91177308-0d34-0410-b5e6-96231b3b80d8
2006-04-02 05:30:25 +00:00
|
|
|
return new StoreInst(II->getOperand(1), Ptr);
|
|
|
|
}
|
|
|
|
break;
|
2006-04-17 22:26:56 +00:00
|
|
|
case Intrinsic::x86_sse_storeu_ps:
|
|
|
|
case Intrinsic::x86_sse2_storeu_pd:
|
|
|
|
case Intrinsic::x86_sse2_storeu_dq:
|
|
|
|
case Intrinsic::x86_sse2_storel_dq:
|
|
|
|
// Turn X86 storeu -> store if the pointer is known aligned.
|
|
|
|
if (GetKnownAlignment(II->getOperand(1), TD) >= 16) {
|
|
|
|
const Type *OpPtrTy = PointerType::get(II->getOperand(2)->getType());
|
|
|
|
Value *Ptr = InsertCastBefore(II->getOperand(1), OpPtrTy, CI);
|
|
|
|
return new StoreInst(II->getOperand(2), Ptr);
|
|
|
|
}
|
|
|
|
break;
|
Lower vperm(x,y, mask) -> shuffle(x,y,mask) if mask is constant. This allows
us to compile oh-so-realistic stuff like this:
vec_vperm(A, B, (vector unsigned char){14});
to:
vspltb v0, v0, 14
instead of:
vspltisb v0, 14
vperm v0, v2, v1, v0
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@27452 91177308-0d34-0410-b5e6-96231b3b80d8
2006-04-06 19:19:17 +00:00
|
|
|
case Intrinsic::ppc_altivec_vperm:
|
|
|
|
// Turn vperm(V1,V2,mask) -> shuffle(V1,V2,mask) if mask is a constant.
|
|
|
|
if (ConstantPacked *Mask = dyn_cast<ConstantPacked>(II->getOperand(3))) {
|
|
|
|
assert(Mask->getNumOperands() == 16 && "Bad type for intrinsic!");
|
|
|
|
|
|
|
|
// Check that all of the elements are integer constants or undefs.
|
|
|
|
bool AllEltsOk = true;
|
|
|
|
for (unsigned i = 0; i != 16; ++i) {
|
|
|
|
if (!isa<ConstantInt>(Mask->getOperand(i)) &&
|
|
|
|
!isa<UndefValue>(Mask->getOperand(i))) {
|
|
|
|
AllEltsOk = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (AllEltsOk) {
|
|
|
|
// Cast the input vectors to byte vectors.
|
|
|
|
Value *Op0 = InsertCastBefore(II->getOperand(1), Mask->getType(), CI);
|
|
|
|
Value *Op1 = InsertCastBefore(II->getOperand(2), Mask->getType(), CI);
|
|
|
|
Value *Result = UndefValue::get(Op0->getType());
|
|
|
|
|
|
|
|
// Only extract each element once.
|
|
|
|
Value *ExtractedElts[32];
|
|
|
|
memset(ExtractedElts, 0, sizeof(ExtractedElts));
|
|
|
|
|
|
|
|
for (unsigned i = 0; i != 16; ++i) {
|
|
|
|
if (isa<UndefValue>(Mask->getOperand(i)))
|
|
|
|
continue;
|
|
|
|
unsigned Idx =cast<ConstantInt>(Mask->getOperand(i))->getRawValue();
|
|
|
|
Idx &= 31; // Match the hardware behavior.
|
|
|
|
|
|
|
|
if (ExtractedElts[Idx] == 0) {
|
|
|
|
Instruction *Elt =
|
|
|
|
new ExtractElementInst(Idx < 16 ? Op0 : Op1,
|
|
|
|
ConstantUInt::get(Type::UIntTy, Idx&15),
|
|
|
|
"tmp");
|
|
|
|
InsertNewInstBefore(Elt, CI);
|
|
|
|
ExtractedElts[Idx] = Elt;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Insert this value into the result vector.
|
|
|
|
Result = new InsertElementInst(Result, ExtractedElts[Idx],
|
|
|
|
ConstantUInt::get(Type::UIntTy, i),
|
|
|
|
"tmp");
|
|
|
|
InsertNewInstBefore(cast<Instruction>(Result), CI);
|
|
|
|
}
|
|
|
|
return new CastInst(Result, CI.getType());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2006-01-13 21:28:09 +00:00
|
|
|
case Intrinsic::stackrestore: {
|
|
|
|
// If the save is right next to the restore, remove the restore. This can
|
|
|
|
// happen when variable allocas are DCE'd.
|
|
|
|
if (IntrinsicInst *SS = dyn_cast<IntrinsicInst>(II->getOperand(1))) {
|
|
|
|
if (SS->getIntrinsicID() == Intrinsic::stacksave) {
|
|
|
|
BasicBlock::iterator BI = SS;
|
|
|
|
if (&*++BI == II)
|
|
|
|
return EraseInstFromFunction(CI);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the stack restore is in a return/unwind block and if there are no
|
|
|
|
// allocas or calls between the restore and the return, nuke the restore.
|
|
|
|
TerminatorInst *TI = II->getParent()->getTerminator();
|
|
|
|
if (isa<ReturnInst>(TI) || isa<UnwindInst>(TI)) {
|
|
|
|
BasicBlock::iterator BI = II;
|
|
|
|
bool CannotRemove = false;
|
|
|
|
for (++BI; &*BI != TI; ++BI) {
|
|
|
|
if (isa<AllocaInst>(BI) ||
|
|
|
|
(isa<CallInst>(BI) && !isa<IntrinsicInst>(BI))) {
|
|
|
|
CannotRemove = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!CannotRemove)
|
|
|
|
return EraseInstFromFunction(CI);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2004-10-12 04:52:52 +00:00
|
|
|
}
|
|
|
|
|
2006-01-13 20:11:04 +00:00
|
|
|
return visitCallSite(II);
|
2003-06-19 17:00:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// InvokeInst simplification
|
|
|
|
//
|
|
|
|
Instruction *InstCombiner::visitInvokeInst(InvokeInst &II) {
|
2003-10-07 22:32:43 +00:00
|
|
|
return visitCallSite(&II);
|
2003-06-19 17:00:31 +00:00
|
|
|
}
|
|
|
|
|
2003-10-07 22:32:43 +00:00
|
|
|
// visitCallSite - Improvements for call and invoke instructions.
|
|
|
|
//
|
|
|
|
Instruction *InstCombiner::visitCallSite(CallSite CS) {
|
2003-10-07 22:54:13 +00:00
|
|
|
bool Changed = false;
|
|
|
|
|
|
|
|
// If the callee is a constexpr cast of a function, attempt to move the cast
|
|
|
|
// to the arguments of the call/invoke.
|
2003-10-07 22:32:43 +00:00
|
|
|
if (transformConstExprCastCall(CS)) return 0;
|
|
|
|
|
2003-10-07 22:54:13 +00:00
|
|
|
Value *Callee = CS.getCalledValue();
|
2004-10-16 18:11:37 +00:00
|
|
|
|
2005-05-13 07:09:09 +00:00
|
|
|
if (Function *CalleeF = dyn_cast<Function>(Callee))
|
|
|
|
if (CalleeF->getCallingConv() != CS.getCallingConv()) {
|
|
|
|
Instruction *OldCall = CS.getInstruction();
|
|
|
|
// If the call and callee calling conventions don't match, this call must
|
|
|
|
// be unreachable, as the call is undefined.
|
|
|
|
new StoreInst(ConstantBool::True,
|
|
|
|
UndefValue::get(PointerType::get(Type::BoolTy)), OldCall);
|
|
|
|
if (!OldCall->use_empty())
|
|
|
|
OldCall->replaceAllUsesWith(UndefValue::get(OldCall->getType()));
|
|
|
|
if (isa<CallInst>(OldCall)) // Not worth removing an invoke here.
|
|
|
|
return EraseInstFromFunction(*OldCall);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2004-10-18 02:59:09 +00:00
|
|
|
if (isa<ConstantPointerNull>(Callee) || isa<UndefValue>(Callee)) {
|
|
|
|
// This instruction is not reachable, just remove it. We insert a store to
|
|
|
|
// undef so that we know that this code is not reachable, despite the fact
|
|
|
|
// that we can't modify the CFG here.
|
|
|
|
new StoreInst(ConstantBool::True,
|
|
|
|
UndefValue::get(PointerType::get(Type::BoolTy)),
|
|
|
|
CS.getInstruction());
|
|
|
|
|
|
|
|
if (!CS.getInstruction()->use_empty())
|
|
|
|
CS.getInstruction()->
|
|
|
|
replaceAllUsesWith(UndefValue::get(CS.getInstruction()->getType()));
|
|
|
|
|
|
|
|
if (InvokeInst *II = dyn_cast<InvokeInst>(CS.getInstruction())) {
|
|
|
|
// Don't break the CFG, insert a dummy cond branch.
|
|
|
|
new BranchInst(II->getNormalDest(), II->getUnwindDest(),
|
|
|
|
ConstantBool::True, II);
|
2004-10-16 18:11:37 +00:00
|
|
|
}
|
2004-10-18 02:59:09 +00:00
|
|
|
return EraseInstFromFunction(*CS.getInstruction());
|
|
|
|
}
|
2004-10-16 18:11:37 +00:00
|
|
|
|
2003-10-07 22:54:13 +00:00
|
|
|
const PointerType *PTy = cast<PointerType>(Callee->getType());
|
|
|
|
const FunctionType *FTy = cast<FunctionType>(PTy->getElementType());
|
|
|
|
if (FTy->isVarArg()) {
|
|
|
|
// See if we can optimize any arguments passed through the varargs area of
|
|
|
|
// the call.
|
|
|
|
for (CallSite::arg_iterator I = CS.arg_begin()+FTy->getNumParams(),
|
|
|
|
E = CS.arg_end(); I != E; ++I)
|
|
|
|
if (CastInst *CI = dyn_cast<CastInst>(*I)) {
|
|
|
|
// If this cast does not effect the value passed through the varargs
|
|
|
|
// area, we can eliminate the use of the cast.
|
|
|
|
Value *Op = CI->getOperand(0);
|
|
|
|
if (CI->getType()->isLosslesslyConvertibleTo(Op->getType())) {
|
|
|
|
*I = Op;
|
|
|
|
Changed = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2003-10-07 22:54:13 +00:00
|
|
|
return Changed ? CS.getInstruction() : 0;
|
2003-10-07 22:32:43 +00:00
|
|
|
}
|
|
|
|
|
2003-06-19 17:00:31 +00:00
|
|
|
// transformConstExprCastCall - If the callee is a constexpr cast of a function,
|
|
|
|
// attempt to move the cast to the arguments of the call/invoke.
|
|
|
|
//
|
|
|
|
bool InstCombiner::transformConstExprCastCall(CallSite CS) {
|
|
|
|
if (!isa<ConstantExpr>(CS.getCalledValue())) return false;
|
|
|
|
ConstantExpr *CE = cast<ConstantExpr>(CS.getCalledValue());
|
2004-07-18 18:59:44 +00:00
|
|
|
if (CE->getOpcode() != Instruction::Cast || !isa<Function>(CE->getOperand(0)))
|
2003-06-19 17:00:31 +00:00
|
|
|
return false;
|
2004-07-18 00:38:32 +00:00
|
|
|
Function *Callee = cast<Function>(CE->getOperand(0));
|
2003-06-19 17:00:31 +00:00
|
|
|
Instruction *Caller = CS.getInstruction();
|
|
|
|
|
|
|
|
// Okay, this is a cast from a function to a different type. Unless doing so
|
|
|
|
// would cause a type conversion of one of our arguments, change this call to
|
|
|
|
// be a direct call with arguments casted to the appropriate types.
|
|
|
|
//
|
|
|
|
const FunctionType *FT = Callee->getFunctionType();
|
|
|
|
const Type *OldRetTy = Caller->getType();
|
|
|
|
|
2004-01-14 06:06:08 +00:00
|
|
|
// Check to see if we are changing the return type...
|
|
|
|
if (OldRetTy != FT->getReturnType()) {
|
|
|
|
if (Callee->isExternal() &&
|
2006-04-20 14:56:47 +00:00
|
|
|
!(OldRetTy->isLosslesslyConvertibleTo(FT->getReturnType()) ||
|
|
|
|
(isa<PointerType>(FT->getReturnType()) &&
|
2006-04-20 15:41:37 +00:00
|
|
|
TD->getIntPtrType()->isLosslesslyConvertibleTo(OldRetTy)))
|
2006-04-20 14:56:47 +00:00
|
|
|
&& !Caller->use_empty())
|
2004-01-14 06:06:08 +00:00
|
|
|
return false; // Cannot transform this return value...
|
|
|
|
|
|
|
|
// If the callsite is an invoke instruction, and the return value is used by
|
|
|
|
// a PHI node in a successor, we cannot change the return type of the call
|
|
|
|
// because there is no place to put the cast instruction (without breaking
|
|
|
|
// the critical edge). Bail out in this case.
|
|
|
|
if (!Caller->use_empty())
|
|
|
|
if (InvokeInst *II = dyn_cast<InvokeInst>(Caller))
|
|
|
|
for (Value::use_iterator UI = II->use_begin(), E = II->use_end();
|
|
|
|
UI != E; ++UI)
|
|
|
|
if (PHINode *PN = dyn_cast<PHINode>(*UI))
|
|
|
|
if (PN->getParent() == II->getNormalDest() ||
|
2004-02-08 21:44:31 +00:00
|
|
|
PN->getParent() == II->getUnwindDest())
|
2004-01-14 06:06:08 +00:00
|
|
|
return false;
|
|
|
|
}
|
2003-06-19 17:00:31 +00:00
|
|
|
|
|
|
|
unsigned NumActualArgs = unsigned(CS.arg_end()-CS.arg_begin());
|
|
|
|
unsigned NumCommonArgs = std::min(FT->getNumParams(), NumActualArgs);
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2003-06-19 17:00:31 +00:00
|
|
|
CallSite::arg_iterator AI = CS.arg_begin();
|
|
|
|
for (unsigned i = 0, e = NumCommonArgs; i != e; ++i, ++AI) {
|
|
|
|
const Type *ParamTy = FT->getParamType(i);
|
|
|
|
bool isConvertible = (*AI)->getType()->isLosslesslyConvertibleTo(ParamTy);
|
2005-04-21 23:48:37 +00:00
|
|
|
if (Callee->isExternal() && !isConvertible) return false;
|
2003-06-19 17:00:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (FT->getNumParams() < NumActualArgs && !FT->isVarArg() &&
|
|
|
|
Callee->isExternal())
|
|
|
|
return false; // Do not delete arguments unless we have a function body...
|
|
|
|
|
|
|
|
// Okay, we decided that this is a safe thing to do: go ahead and start
|
|
|
|
// inserting cast instructions as necessary...
|
|
|
|
std::vector<Value*> Args;
|
|
|
|
Args.reserve(NumActualArgs);
|
|
|
|
|
|
|
|
AI = CS.arg_begin();
|
|
|
|
for (unsigned i = 0; i != NumCommonArgs; ++i, ++AI) {
|
|
|
|
const Type *ParamTy = FT->getParamType(i);
|
|
|
|
if ((*AI)->getType() == ParamTy) {
|
|
|
|
Args.push_back(*AI);
|
|
|
|
} else {
|
2004-04-08 04:43:23 +00:00
|
|
|
Args.push_back(InsertNewInstBefore(new CastInst(*AI, ParamTy, "tmp"),
|
|
|
|
*Caller));
|
2003-06-19 17:00:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the function takes more arguments than the call was taking, add them
|
|
|
|
// now...
|
|
|
|
for (unsigned i = NumCommonArgs; i != FT->getNumParams(); ++i)
|
|
|
|
Args.push_back(Constant::getNullValue(FT->getParamType(i)));
|
|
|
|
|
|
|
|
// If we are removing arguments to the function, emit an obnoxious warning...
|
|
|
|
if (FT->getNumParams() < NumActualArgs)
|
|
|
|
if (!FT->isVarArg()) {
|
|
|
|
std::cerr << "WARNING: While resolving call to function '"
|
|
|
|
<< Callee->getName() << "' arguments were dropped!\n";
|
|
|
|
} else {
|
|
|
|
// Add all of the arguments in their promoted form to the arg list...
|
|
|
|
for (unsigned i = FT->getNumParams(); i != NumActualArgs; ++i, ++AI) {
|
|
|
|
const Type *PTy = getPromotedType((*AI)->getType());
|
|
|
|
if (PTy != (*AI)->getType()) {
|
|
|
|
// Must promote to pass through va_arg area!
|
|
|
|
Instruction *Cast = new CastInst(*AI, PTy, "tmp");
|
|
|
|
InsertNewInstBefore(Cast, *Caller);
|
|
|
|
Args.push_back(Cast);
|
|
|
|
} else {
|
|
|
|
Args.push_back(*AI);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (FT->getReturnType() == Type::VoidTy)
|
|
|
|
Caller->setName(""); // Void type should not have a name...
|
|
|
|
|
|
|
|
Instruction *NC;
|
|
|
|
if (InvokeInst *II = dyn_cast<InvokeInst>(Caller)) {
|
2004-02-08 21:44:31 +00:00
|
|
|
NC = new InvokeInst(Callee, II->getNormalDest(), II->getUnwindDest(),
|
2003-06-19 17:00:31 +00:00
|
|
|
Args, Caller->getName(), Caller);
|
2005-05-14 12:25:32 +00:00
|
|
|
cast<InvokeInst>(II)->setCallingConv(II->getCallingConv());
|
2003-06-19 17:00:31 +00:00
|
|
|
} else {
|
|
|
|
NC = new CallInst(Callee, Args, Caller->getName(), Caller);
|
2005-05-06 06:48:21 +00:00
|
|
|
if (cast<CallInst>(Caller)->isTailCall())
|
|
|
|
cast<CallInst>(NC)->setTailCall();
|
2005-05-14 12:25:32 +00:00
|
|
|
cast<CallInst>(NC)->setCallingConv(cast<CallInst>(Caller)->getCallingConv());
|
2003-06-19 17:00:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Insert a cast of the return type as necessary...
|
|
|
|
Value *NV = NC;
|
|
|
|
if (Caller->getType() != NV->getType() && !Caller->use_empty()) {
|
|
|
|
if (NV->getType() != Type::VoidTy) {
|
|
|
|
NV = NC = new CastInst(NC, Caller->getType(), "tmp");
|
2003-10-30 00:46:41 +00:00
|
|
|
|
|
|
|
// If this is an invoke instruction, we should insert it after the first
|
|
|
|
// non-phi, instruction in the normal successor block.
|
|
|
|
if (InvokeInst *II = dyn_cast<InvokeInst>(Caller)) {
|
|
|
|
BasicBlock::iterator I = II->getNormalDest()->begin();
|
|
|
|
while (isa<PHINode>(I)) ++I;
|
|
|
|
InsertNewInstBefore(NC, *I);
|
|
|
|
} else {
|
|
|
|
// Otherwise, it's a call, just insert cast right after the call instr
|
|
|
|
InsertNewInstBefore(NC, *Caller);
|
|
|
|
}
|
2004-02-28 05:22:00 +00:00
|
|
|
AddUsersToWorkList(*Caller);
|
2003-06-19 17:00:31 +00:00
|
|
|
} else {
|
2004-10-17 21:22:38 +00:00
|
|
|
NV = UndefValue::get(Caller->getType());
|
2003-06-19 17:00:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Caller->getType() != Type::VoidTy && !Caller->use_empty())
|
|
|
|
Caller->replaceAllUsesWith(NV);
|
|
|
|
Caller->getParent()->getInstList().erase(Caller);
|
|
|
|
removeFromWorkList(Caller);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-11-14 19:13:23 +00:00
|
|
|
// FoldPHIArgOpIntoPHI - If all operands to a PHI node are the same "unary"
|
|
|
|
// operator and they all are only used by the PHI, PHI together their
|
|
|
|
// inputs, and do the operation once, to the result of the PHI.
|
|
|
|
Instruction *InstCombiner::FoldPHIArgOpIntoPHI(PHINode &PN) {
|
|
|
|
Instruction *FirstInst = cast<Instruction>(PN.getIncomingValue(0));
|
|
|
|
|
|
|
|
// Scan the instruction, looking for input operations that can be folded away.
|
|
|
|
// If all input operands to the phi are the same instruction (e.g. a cast from
|
|
|
|
// the same type or "+42") we can pull the operation through the PHI, reducing
|
|
|
|
// code size and simplifying code.
|
|
|
|
Constant *ConstantOp = 0;
|
|
|
|
const Type *CastSrcTy = 0;
|
|
|
|
if (isa<CastInst>(FirstInst)) {
|
|
|
|
CastSrcTy = FirstInst->getOperand(0)->getType();
|
|
|
|
} else if (isa<BinaryOperator>(FirstInst) || isa<ShiftInst>(FirstInst)) {
|
|
|
|
// Can fold binop or shift if the RHS is a constant.
|
|
|
|
ConstantOp = dyn_cast<Constant>(FirstInst->getOperand(1));
|
|
|
|
if (ConstantOp == 0) return 0;
|
|
|
|
} else {
|
|
|
|
return 0; // Cannot fold this operation.
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check to see if all arguments are the same operation.
|
|
|
|
for (unsigned i = 1, e = PN.getNumIncomingValues(); i != e; ++i) {
|
|
|
|
if (!isa<Instruction>(PN.getIncomingValue(i))) return 0;
|
|
|
|
Instruction *I = cast<Instruction>(PN.getIncomingValue(i));
|
|
|
|
if (!I->hasOneUse() || I->getOpcode() != FirstInst->getOpcode())
|
|
|
|
return 0;
|
|
|
|
if (CastSrcTy) {
|
|
|
|
if (I->getOperand(0)->getType() != CastSrcTy)
|
|
|
|
return 0; // Cast operation must match.
|
|
|
|
} else if (I->getOperand(1) != ConstantOp) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Okay, they are all the same operation. Create a new PHI node of the
|
|
|
|
// correct type, and PHI together all of the LHS's of the instructions.
|
|
|
|
PHINode *NewPN = new PHINode(FirstInst->getOperand(0)->getType(),
|
|
|
|
PN.getName()+".in");
|
2005-01-29 00:39:08 +00:00
|
|
|
NewPN->reserveOperandSpace(PN.getNumOperands()/2);
|
2004-11-14 19:29:34 +00:00
|
|
|
|
|
|
|
Value *InVal = FirstInst->getOperand(0);
|
|
|
|
NewPN->addIncoming(InVal, PN.getIncomingBlock(0));
|
2004-11-14 19:13:23 +00:00
|
|
|
|
|
|
|
// Add all operands to the new PHI.
|
2004-11-14 19:29:34 +00:00
|
|
|
for (unsigned i = 1, e = PN.getNumIncomingValues(); i != e; ++i) {
|
|
|
|
Value *NewInVal = cast<Instruction>(PN.getIncomingValue(i))->getOperand(0);
|
|
|
|
if (NewInVal != InVal)
|
|
|
|
InVal = 0;
|
|
|
|
NewPN->addIncoming(NewInVal, PN.getIncomingBlock(i));
|
|
|
|
}
|
|
|
|
|
|
|
|
Value *PhiVal;
|
|
|
|
if (InVal) {
|
|
|
|
// The new PHI unions all of the same values together. This is really
|
|
|
|
// common, so we handle it intelligently here for compile-time speed.
|
|
|
|
PhiVal = InVal;
|
|
|
|
delete NewPN;
|
|
|
|
} else {
|
|
|
|
InsertNewInstBefore(NewPN, PN);
|
|
|
|
PhiVal = NewPN;
|
|
|
|
}
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2004-11-14 19:13:23 +00:00
|
|
|
// Insert and return the new operation.
|
|
|
|
if (isa<CastInst>(FirstInst))
|
2004-11-14 19:29:34 +00:00
|
|
|
return new CastInst(PhiVal, PN.getType());
|
2004-11-14 19:13:23 +00:00
|
|
|
else if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(FirstInst))
|
2004-11-14 19:29:34 +00:00
|
|
|
return BinaryOperator::create(BinOp->getOpcode(), PhiVal, ConstantOp);
|
2004-11-14 19:13:23 +00:00
|
|
|
else
|
|
|
|
return new ShiftInst(cast<ShiftInst>(FirstInst)->getOpcode(),
|
2004-11-14 19:29:34 +00:00
|
|
|
PhiVal, ConstantOp);
|
2004-11-14 19:13:23 +00:00
|
|
|
}
|
2002-05-02 17:06:02 +00:00
|
|
|
|
2005-01-17 05:10:15 +00:00
|
|
|
/// DeadPHICycle - Return true if this PHI node is only used by a PHI node cycle
|
|
|
|
/// that is dead.
|
|
|
|
static bool DeadPHICycle(PHINode *PN, std::set<PHINode*> &PotentiallyDeadPHIs) {
|
|
|
|
if (PN->use_empty()) return true;
|
|
|
|
if (!PN->hasOneUse()) return false;
|
|
|
|
|
|
|
|
// Remember this node, and if we find the cycle, return.
|
|
|
|
if (!PotentiallyDeadPHIs.insert(PN).second)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (PHINode *PU = dyn_cast<PHINode>(PN->use_back()))
|
|
|
|
return DeadPHICycle(PU, PotentiallyDeadPHIs);
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2005-01-17 05:10:15 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2002-05-06 18:06:38 +00:00
|
|
|
// PHINode simplification
|
|
|
|
//
|
2002-06-25 16:13:24 +00:00
|
|
|
Instruction *InstCombiner::visitPHINode(PHINode &PN) {
|
2005-08-05 01:04:30 +00:00
|
|
|
if (Value *V = PN.hasConstantValue())
|
|
|
|
return ReplaceInstUsesWith(PN, V);
|
2004-02-16 05:07:08 +00:00
|
|
|
|
|
|
|
// If the only user of this instruction is a cast instruction, and all of the
|
|
|
|
// incoming values are constants, change this PHI to merge together the casted
|
|
|
|
// constants.
|
|
|
|
if (PN.hasOneUse())
|
|
|
|
if (CastInst *CI = dyn_cast<CastInst>(PN.use_back()))
|
|
|
|
if (CI->getType() != PN.getType()) { // noop casts will be folded
|
|
|
|
bool AllConstant = true;
|
|
|
|
for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i)
|
|
|
|
if (!isa<Constant>(PN.getIncomingValue(i))) {
|
|
|
|
AllConstant = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (AllConstant) {
|
|
|
|
// Make a new PHI with all casted values.
|
|
|
|
PHINode *New = new PHINode(CI->getType(), PN.getName(), &PN);
|
|
|
|
for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) {
|
|
|
|
Constant *OldArg = cast<Constant>(PN.getIncomingValue(i));
|
|
|
|
New->addIncoming(ConstantExpr::getCast(OldArg, New->getType()),
|
|
|
|
PN.getIncomingBlock(i));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update the cast instruction.
|
|
|
|
CI->setOperand(0, New);
|
|
|
|
WorkList.push_back(CI); // revisit the cast instruction to fold.
|
|
|
|
WorkList.push_back(New); // Make sure to revisit the new Phi
|
|
|
|
return &PN; // PN is now dead!
|
|
|
|
}
|
|
|
|
}
|
2004-11-14 19:13:23 +00:00
|
|
|
|
|
|
|
// If all PHI operands are the same operation, pull them through the PHI,
|
|
|
|
// reducing code size.
|
|
|
|
if (isa<Instruction>(PN.getIncomingValue(0)) &&
|
|
|
|
PN.getIncomingValue(0)->hasOneUse())
|
|
|
|
if (Instruction *Result = FoldPHIArgOpIntoPHI(PN))
|
|
|
|
return Result;
|
|
|
|
|
2005-01-17 05:10:15 +00:00
|
|
|
// If this is a trivial cycle in the PHI node graph, remove it. Basically, if
|
|
|
|
// this PHI only has a single use (a PHI), and if that PHI only has one use (a
|
|
|
|
// PHI)... break the cycle.
|
|
|
|
if (PN.hasOneUse())
|
|
|
|
if (PHINode *PU = dyn_cast<PHINode>(PN.use_back())) {
|
|
|
|
std::set<PHINode*> PotentiallyDeadPHIs;
|
|
|
|
PotentiallyDeadPHIs.insert(&PN);
|
|
|
|
if (DeadPHICycle(PU, PotentiallyDeadPHIs))
|
|
|
|
return ReplaceInstUsesWith(PN, UndefValue::get(PN.getType()));
|
|
|
|
}
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2003-12-19 05:58:40 +00:00
|
|
|
return 0;
|
2002-05-06 18:06:38 +00:00
|
|
|
}
|
|
|
|
|
2004-04-05 01:30:19 +00:00
|
|
|
static Value *InsertSignExtendToPtrTy(Value *V, const Type *DTy,
|
|
|
|
Instruction *InsertPoint,
|
|
|
|
InstCombiner *IC) {
|
|
|
|
unsigned PS = IC->getTargetData().getPointerSize();
|
|
|
|
const Type *VTy = V->getType();
|
|
|
|
if (!VTy->isSigned() && VTy->getPrimitiveSize() < PS)
|
|
|
|
// We must insert a cast to ensure we sign-extend.
|
|
|
|
V = IC->InsertNewInstBefore(new CastInst(V, VTy->getSignedVersion(),
|
|
|
|
V->getName()), *InsertPoint);
|
|
|
|
return IC->InsertNewInstBefore(new CastInst(V, DTy, V->getName()),
|
|
|
|
*InsertPoint);
|
|
|
|
}
|
|
|
|
|
2002-05-02 17:06:02 +00:00
|
|
|
|
2002-06-25 16:13:24 +00:00
|
|
|
Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) {
|
2004-05-07 22:09:22 +00:00
|
|
|
Value *PtrOp = GEP.getOperand(0);
|
2003-05-22 19:07:21 +00:00
|
|
|
// Is it 'getelementptr %P, long 0' or 'getelementptr %P'
|
2002-06-25 16:13:24 +00:00
|
|
|
// If so, eliminate the noop.
|
2004-02-22 05:25:17 +00:00
|
|
|
if (GEP.getNumOperands() == 1)
|
2004-05-07 22:09:22 +00:00
|
|
|
return ReplaceInstUsesWith(GEP, PtrOp);
|
2004-02-22 05:25:17 +00:00
|
|
|
|
2004-10-16 18:11:37 +00:00
|
|
|
if (isa<UndefValue>(GEP.getOperand(0)))
|
|
|
|
return ReplaceInstUsesWith(GEP, UndefValue::get(GEP.getType()));
|
|
|
|
|
2004-02-22 05:25:17 +00:00
|
|
|
bool HasZeroPointerIndex = false;
|
|
|
|
if (Constant *C = dyn_cast<Constant>(GEP.getOperand(1)))
|
|
|
|
HasZeroPointerIndex = C->isNullValue();
|
|
|
|
|
|
|
|
if (GEP.getNumOperands() == 2 && HasZeroPointerIndex)
|
2004-05-07 22:09:22 +00:00
|
|
|
return ReplaceInstUsesWith(GEP, PtrOp);
|
2002-05-02 17:06:02 +00:00
|
|
|
|
2004-04-05 01:30:19 +00:00
|
|
|
// Eliminate unneeded casts for indices.
|
|
|
|
bool MadeChange = false;
|
2004-04-07 18:38:20 +00:00
|
|
|
gep_type_iterator GTI = gep_type_begin(GEP);
|
|
|
|
for (unsigned i = 1, e = GEP.getNumOperands(); i != e; ++i, ++GTI)
|
|
|
|
if (isa<SequentialType>(*GTI)) {
|
|
|
|
if (CastInst *CI = dyn_cast<CastInst>(GEP.getOperand(i))) {
|
|
|
|
Value *Src = CI->getOperand(0);
|
|
|
|
const Type *SrcTy = Src->getType();
|
|
|
|
const Type *DestTy = CI->getType();
|
|
|
|
if (Src->getType()->isInteger()) {
|
2005-04-24 06:59:08 +00:00
|
|
|
if (SrcTy->getPrimitiveSizeInBits() ==
|
|
|
|
DestTy->getPrimitiveSizeInBits()) {
|
2004-04-07 18:38:20 +00:00
|
|
|
// We can always eliminate a cast from ulong or long to the other.
|
|
|
|
// We can always eliminate a cast from uint to int or the other on
|
|
|
|
// 32-bit pointer platforms.
|
2005-04-24 06:59:08 +00:00
|
|
|
if (DestTy->getPrimitiveSizeInBits() >= TD->getPointerSizeInBits()){
|
2004-04-07 18:38:20 +00:00
|
|
|
MadeChange = true;
|
|
|
|
GEP.setOperand(i, Src);
|
|
|
|
}
|
|
|
|
} else if (SrcTy->getPrimitiveSize() < DestTy->getPrimitiveSize() &&
|
|
|
|
SrcTy->getPrimitiveSize() == 4) {
|
|
|
|
// We can always eliminate a cast from int to [u]long. We can
|
|
|
|
// eliminate a cast from uint to [u]long iff the target is a 32-bit
|
|
|
|
// pointer target.
|
2005-04-21 23:48:37 +00:00
|
|
|
if (SrcTy->isSigned() ||
|
2005-04-24 06:59:08 +00:00
|
|
|
SrcTy->getPrimitiveSizeInBits() >= TD->getPointerSizeInBits()) {
|
2004-04-07 18:38:20 +00:00
|
|
|
MadeChange = true;
|
|
|
|
GEP.setOperand(i, Src);
|
|
|
|
}
|
2004-04-05 01:30:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-04-07 18:38:20 +00:00
|
|
|
// If we are using a wider index than needed for this platform, shrink it
|
|
|
|
// to what we need. If the incoming value needs a cast instruction,
|
|
|
|
// insert it. This explicit cast can make subsequent optimizations more
|
|
|
|
// obvious.
|
|
|
|
Value *Op = GEP.getOperand(i);
|
|
|
|
if (Op->getType()->getPrimitiveSize() > TD->getPointerSize())
|
Fix a HUGE pessimization on X86. The indvars pass was taking this
(familiar) function:
int _strlen(const char *str) {
int len = 0;
while (*str++) len++;
return len;
}
And transforming it to use a ulong induction variable, because the type of
the pointer index was left as a constant long. This is obviously very bad.
The fix is to shrink long constants in getelementptr instructions to intptr_t,
making the indvars pass insert a uint induction variable, which is much more
efficient.
Here's the before code for this function:
int %_strlen(sbyte* %str) {
entry:
%tmp.13 = load sbyte* %str ; <sbyte> [#uses=1]
%tmp.24 = seteq sbyte %tmp.13, 0 ; <bool> [#uses=1]
br bool %tmp.24, label %loopexit, label %no_exit
no_exit: ; preds = %entry, %no_exit
*** %indvar = phi uint [ %indvar.next, %no_exit ], [ 0, %entry ] ; <uint> [#uses=2]
*** %indvar = phi ulong [ %indvar.next, %no_exit ], [ 0, %entry ] ; <ulong> [#uses=2]
%indvar1 = cast ulong %indvar to uint ; <uint> [#uses=1]
%inc.02.sum = add uint %indvar1, 1 ; <uint> [#uses=1]
%inc.0.0 = getelementptr sbyte* %str, uint %inc.02.sum ; <sbyte*> [#uses=1]
%tmp.1 = load sbyte* %inc.0.0 ; <sbyte> [#uses=1]
%tmp.2 = seteq sbyte %tmp.1, 0 ; <bool> [#uses=1]
%indvar.next = add ulong %indvar, 1 ; <ulong> [#uses=1]
%indvar.next = add uint %indvar, 1 ; <uint> [#uses=1]
br bool %tmp.2, label %loopexit.loopexit, label %no_exit
loopexit.loopexit: ; preds = %no_exit
%indvar = cast uint %indvar to int ; <int> [#uses=1]
%inc.1 = add int %indvar, 1 ; <int> [#uses=1]
ret int %inc.1
loopexit: ; preds = %entry
ret int 0
}
Here's the after code:
int %_strlen(sbyte* %str) {
entry:
%inc.02 = getelementptr sbyte* %str, uint 1 ; <sbyte*> [#uses=1]
%tmp.13 = load sbyte* %str ; <sbyte> [#uses=1]
%tmp.24 = seteq sbyte %tmp.13, 0 ; <bool> [#uses=1]
br bool %tmp.24, label %loopexit, label %no_exit
no_exit: ; preds = %entry, %no_exit
*** %indvar = phi uint [ %indvar.next, %no_exit ], [ 0, %entry ] ; <uint> [#uses=3]
%indvar = cast uint %indvar to int ; <int> [#uses=1]
%inc.0.0 = getelementptr sbyte* %inc.02, uint %indvar ; <sbyte*> [#uses=1]
%inc.1 = add int %indvar, 1 ; <int> [#uses=1]
%tmp.1 = load sbyte* %inc.0.0 ; <sbyte> [#uses=1]
%tmp.2 = seteq sbyte %tmp.1, 0 ; <bool> [#uses=1]
%indvar.next = add uint %indvar, 1 ; <uint> [#uses=1]
br bool %tmp.2, label %loopexit, label %no_exit
loopexit: ; preds = %entry, %no_exit
%len.0.1 = phi int [ 0, %entry ], [ %inc.1, %no_exit ] ; <int> [#uses=1]
ret int %len.0.1
}
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@13016 91177308-0d34-0410-b5e6-96231b3b80d8
2004-04-17 18:16:10 +00:00
|
|
|
if (Constant *C = dyn_cast<Constant>(Op)) {
|
2004-07-20 01:48:15 +00:00
|
|
|
GEP.setOperand(i, ConstantExpr::getCast(C,
|
|
|
|
TD->getIntPtrType()->getSignedVersion()));
|
Fix a HUGE pessimization on X86. The indvars pass was taking this
(familiar) function:
int _strlen(const char *str) {
int len = 0;
while (*str++) len++;
return len;
}
And transforming it to use a ulong induction variable, because the type of
the pointer index was left as a constant long. This is obviously very bad.
The fix is to shrink long constants in getelementptr instructions to intptr_t,
making the indvars pass insert a uint induction variable, which is much more
efficient.
Here's the before code for this function:
int %_strlen(sbyte* %str) {
entry:
%tmp.13 = load sbyte* %str ; <sbyte> [#uses=1]
%tmp.24 = seteq sbyte %tmp.13, 0 ; <bool> [#uses=1]
br bool %tmp.24, label %loopexit, label %no_exit
no_exit: ; preds = %entry, %no_exit
*** %indvar = phi uint [ %indvar.next, %no_exit ], [ 0, %entry ] ; <uint> [#uses=2]
*** %indvar = phi ulong [ %indvar.next, %no_exit ], [ 0, %entry ] ; <ulong> [#uses=2]
%indvar1 = cast ulong %indvar to uint ; <uint> [#uses=1]
%inc.02.sum = add uint %indvar1, 1 ; <uint> [#uses=1]
%inc.0.0 = getelementptr sbyte* %str, uint %inc.02.sum ; <sbyte*> [#uses=1]
%tmp.1 = load sbyte* %inc.0.0 ; <sbyte> [#uses=1]
%tmp.2 = seteq sbyte %tmp.1, 0 ; <bool> [#uses=1]
%indvar.next = add ulong %indvar, 1 ; <ulong> [#uses=1]
%indvar.next = add uint %indvar, 1 ; <uint> [#uses=1]
br bool %tmp.2, label %loopexit.loopexit, label %no_exit
loopexit.loopexit: ; preds = %no_exit
%indvar = cast uint %indvar to int ; <int> [#uses=1]
%inc.1 = add int %indvar, 1 ; <int> [#uses=1]
ret int %inc.1
loopexit: ; preds = %entry
ret int 0
}
Here's the after code:
int %_strlen(sbyte* %str) {
entry:
%inc.02 = getelementptr sbyte* %str, uint 1 ; <sbyte*> [#uses=1]
%tmp.13 = load sbyte* %str ; <sbyte> [#uses=1]
%tmp.24 = seteq sbyte %tmp.13, 0 ; <bool> [#uses=1]
br bool %tmp.24, label %loopexit, label %no_exit
no_exit: ; preds = %entry, %no_exit
*** %indvar = phi uint [ %indvar.next, %no_exit ], [ 0, %entry ] ; <uint> [#uses=3]
%indvar = cast uint %indvar to int ; <int> [#uses=1]
%inc.0.0 = getelementptr sbyte* %inc.02, uint %indvar ; <sbyte*> [#uses=1]
%inc.1 = add int %indvar, 1 ; <int> [#uses=1]
%tmp.1 = load sbyte* %inc.0.0 ; <sbyte> [#uses=1]
%tmp.2 = seteq sbyte %tmp.1, 0 ; <bool> [#uses=1]
%indvar.next = add uint %indvar, 1 ; <uint> [#uses=1]
br bool %tmp.2, label %loopexit, label %no_exit
loopexit: ; preds = %entry, %no_exit
%len.0.1 = phi int [ 0, %entry ], [ %inc.1, %no_exit ] ; <int> [#uses=1]
ret int %len.0.1
}
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@13016 91177308-0d34-0410-b5e6-96231b3b80d8
2004-04-17 18:16:10 +00:00
|
|
|
MadeChange = true;
|
|
|
|
} else {
|
2004-04-07 18:38:20 +00:00
|
|
|
Op = InsertNewInstBefore(new CastInst(Op, TD->getIntPtrType(),
|
|
|
|
Op->getName()), GEP);
|
|
|
|
GEP.setOperand(i, Op);
|
|
|
|
MadeChange = true;
|
|
|
|
}
|
2004-07-20 01:48:15 +00:00
|
|
|
|
|
|
|
// If this is a constant idx, make sure to canonicalize it to be a signed
|
|
|
|
// operand, otherwise CSE and other optimizations are pessimized.
|
|
|
|
if (ConstantUInt *CUI = dyn_cast<ConstantUInt>(Op)) {
|
|
|
|
GEP.setOperand(i, ConstantExpr::getCast(CUI,
|
|
|
|
CUI->getType()->getSignedVersion()));
|
|
|
|
MadeChange = true;
|
|
|
|
}
|
2004-04-05 01:30:19 +00:00
|
|
|
}
|
|
|
|
if (MadeChange) return &GEP;
|
|
|
|
|
2002-08-02 19:29:35 +00:00
|
|
|
// Combine Indices - If the source pointer to this getelementptr instruction
|
|
|
|
// is a getelementptr instruction, combine the indices of the two
|
|
|
|
// getelementptr instructions into a single instruction.
|
|
|
|
//
|
2004-03-25 22:59:29 +00:00
|
|
|
std::vector<Value*> SrcGEPOperands;
|
2005-01-13 20:14:25 +00:00
|
|
|
if (User *Src = dyn_castGetElementPtr(PtrOp))
|
2004-03-25 22:59:29 +00:00
|
|
|
SrcGEPOperands.assign(Src->op_begin(), Src->op_end());
|
|
|
|
|
|
|
|
if (!SrcGEPOperands.empty()) {
|
2004-05-07 22:09:22 +00:00
|
|
|
// Note that if our source is a gep chain itself that we wait for that
|
|
|
|
// chain to be resolved before we perform this transformation. This
|
|
|
|
// avoids us creating a TON of code in some cases.
|
|
|
|
//
|
|
|
|
if (isa<GetElementPtrInst>(SrcGEPOperands[0]) &&
|
|
|
|
cast<Instruction>(SrcGEPOperands[0])->getNumOperands() == 2)
|
|
|
|
return 0; // Wait until our source is folded to completion.
|
|
|
|
|
2002-08-02 19:29:35 +00:00
|
|
|
std::vector<Value *> Indices;
|
2004-05-07 22:09:22 +00:00
|
|
|
|
|
|
|
// Find out whether the last index in the source GEP is a sequential idx.
|
|
|
|
bool EndsWithSequential = false;
|
|
|
|
for (gep_type_iterator I = gep_type_begin(*cast<User>(PtrOp)),
|
|
|
|
E = gep_type_end(*cast<User>(PtrOp)); I != E; ++I)
|
2004-05-08 22:41:42 +00:00
|
|
|
EndsWithSequential = !isa<StructType>(*I);
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2002-08-02 19:29:35 +00:00
|
|
|
// Can we combine the two pointer arithmetics offsets?
|
2004-05-07 22:09:22 +00:00
|
|
|
if (EndsWithSequential) {
|
2003-03-05 22:33:14 +00:00
|
|
|
// Replace: gep (gep %P, long B), long A, ...
|
|
|
|
// With: T = long A+B; gep %P, T, ...
|
|
|
|
//
|
2004-05-07 22:09:22 +00:00
|
|
|
Value *Sum, *SO1 = SrcGEPOperands.back(), *GO1 = GEP.getOperand(1);
|
2004-04-05 01:30:19 +00:00
|
|
|
if (SO1 == Constant::getNullValue(SO1->getType())) {
|
|
|
|
Sum = GO1;
|
|
|
|
} else if (GO1 == Constant::getNullValue(GO1->getType())) {
|
|
|
|
Sum = SO1;
|
|
|
|
} else {
|
|
|
|
// If they aren't the same type, convert both to an integer of the
|
|
|
|
// target's pointer size.
|
|
|
|
if (SO1->getType() != GO1->getType()) {
|
|
|
|
if (Constant *SO1C = dyn_cast<Constant>(SO1)) {
|
|
|
|
SO1 = ConstantExpr::getCast(SO1C, GO1->getType());
|
|
|
|
} else if (Constant *GO1C = dyn_cast<Constant>(GO1)) {
|
|
|
|
GO1 = ConstantExpr::getCast(GO1C, SO1->getType());
|
|
|
|
} else {
|
|
|
|
unsigned PS = TD->getPointerSize();
|
|
|
|
if (SO1->getType()->getPrimitiveSize() == PS) {
|
|
|
|
// Convert GO1 to SO1's type.
|
|
|
|
GO1 = InsertSignExtendToPtrTy(GO1, SO1->getType(), &GEP, this);
|
|
|
|
|
|
|
|
} else if (GO1->getType()->getPrimitiveSize() == PS) {
|
|
|
|
// Convert SO1 to GO1's type.
|
|
|
|
SO1 = InsertSignExtendToPtrTy(SO1, GO1->getType(), &GEP, this);
|
|
|
|
} else {
|
|
|
|
const Type *PT = TD->getIntPtrType();
|
|
|
|
SO1 = InsertSignExtendToPtrTy(SO1, PT, &GEP, this);
|
|
|
|
GO1 = InsertSignExtendToPtrTy(GO1, PT, &GEP, this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-05-07 22:09:22 +00:00
|
|
|
if (isa<Constant>(SO1) && isa<Constant>(GO1))
|
|
|
|
Sum = ConstantExpr::getAdd(cast<Constant>(SO1), cast<Constant>(GO1));
|
|
|
|
else {
|
2004-06-10 02:07:29 +00:00
|
|
|
Sum = BinaryOperator::createAdd(SO1, GO1, PtrOp->getName()+".sum");
|
|
|
|
InsertNewInstBefore(cast<Instruction>(Sum), GEP);
|
2004-05-07 22:09:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Recycle the GEP we already have if possible.
|
|
|
|
if (SrcGEPOperands.size() == 2) {
|
|
|
|
GEP.setOperand(0, SrcGEPOperands[0]);
|
|
|
|
GEP.setOperand(1, Sum);
|
|
|
|
return &GEP;
|
|
|
|
} else {
|
|
|
|
Indices.insert(Indices.end(), SrcGEPOperands.begin()+1,
|
|
|
|
SrcGEPOperands.end()-1);
|
|
|
|
Indices.push_back(Sum);
|
|
|
|
Indices.insert(Indices.end(), GEP.op_begin()+2, GEP.op_end());
|
2004-04-05 01:30:19 +00:00
|
|
|
}
|
2005-04-21 23:48:37 +00:00
|
|
|
} else if (isa<Constant>(*GEP.idx_begin()) &&
|
2004-04-05 01:30:19 +00:00
|
|
|
cast<Constant>(*GEP.idx_begin())->isNullValue() &&
|
2005-04-21 23:48:37 +00:00
|
|
|
SrcGEPOperands.size() != 1) {
|
2002-08-02 19:29:35 +00:00
|
|
|
// Otherwise we can do the fold if the first index of the GEP is a zero
|
2004-03-25 22:59:29 +00:00
|
|
|
Indices.insert(Indices.end(), SrcGEPOperands.begin()+1,
|
|
|
|
SrcGEPOperands.end());
|
2002-08-02 19:29:35 +00:00
|
|
|
Indices.insert(Indices.end(), GEP.idx_begin()+1, GEP.idx_end());
|
|
|
|
}
|
2001-12-14 16:52:21 +00:00
|
|
|
|
2002-08-02 19:29:35 +00:00
|
|
|
if (!Indices.empty())
|
2004-03-25 22:59:29 +00:00
|
|
|
return new GetElementPtrInst(SrcGEPOperands[0], Indices, GEP.getName());
|
2002-08-17 22:21:59 +00:00
|
|
|
|
2004-05-07 22:09:22 +00:00
|
|
|
} else if (GlobalValue *GV = dyn_cast<GlobalValue>(PtrOp)) {
|
2002-08-17 22:21:59 +00:00
|
|
|
// GEP of global variable. If all of the indices for this GEP are
|
|
|
|
// constants, we can promote this to a constexpr instead of an instruction.
|
|
|
|
|
|
|
|
// Scan for nonconstants...
|
|
|
|
std::vector<Constant*> Indices;
|
|
|
|
User::op_iterator I = GEP.idx_begin(), E = GEP.idx_end();
|
|
|
|
for (; I != E && isa<Constant>(*I); ++I)
|
|
|
|
Indices.push_back(cast<Constant>(*I));
|
|
|
|
|
|
|
|
if (I == E) { // If they are all constants...
|
2004-07-18 18:59:44 +00:00
|
|
|
Constant *CE = ConstantExpr::getGetElementPtr(GV, Indices);
|
2002-08-17 22:21:59 +00:00
|
|
|
|
|
|
|
// Replace all uses of the GEP with the new constexpr...
|
|
|
|
return ReplaceInstUsesWith(GEP, CE);
|
|
|
|
}
|
2005-09-13 00:40:14 +00:00
|
|
|
} else if (Value *X = isCast(PtrOp)) { // Is the operand a cast?
|
|
|
|
if (!isa<PointerType>(X->getType())) {
|
|
|
|
// Not interesting. Source pointer must be a cast from pointer.
|
|
|
|
} else if (HasZeroPointerIndex) {
|
|
|
|
// transform: GEP (cast [10 x ubyte]* X to [0 x ubyte]*), long 0, ...
|
|
|
|
// into : GEP [10 x ubyte]* X, long 0, ...
|
|
|
|
//
|
|
|
|
// This occurs when the program declares an array extern like "int X[];"
|
|
|
|
//
|
|
|
|
const PointerType *CPTy = cast<PointerType>(PtrOp->getType());
|
|
|
|
const PointerType *XTy = cast<PointerType>(X->getType());
|
|
|
|
if (const ArrayType *XATy =
|
|
|
|
dyn_cast<ArrayType>(XTy->getElementType()))
|
|
|
|
if (const ArrayType *CATy =
|
|
|
|
dyn_cast<ArrayType>(CPTy->getElementType()))
|
|
|
|
if (CATy->getElementType() == XATy->getElementType()) {
|
|
|
|
// At this point, we know that the cast source type is a pointer
|
|
|
|
// to an array of the same type as the destination pointer
|
|
|
|
// array. Because the array type is never stepped over (there
|
|
|
|
// is a leading zero) we can fold the cast into this GEP.
|
|
|
|
GEP.setOperand(0, X);
|
|
|
|
return &GEP;
|
|
|
|
}
|
|
|
|
} else if (GEP.getNumOperands() == 2) {
|
|
|
|
// Transform things like:
|
2005-09-13 18:36:04 +00:00
|
|
|
// %t = getelementptr ubyte* cast ([2 x int]* %str to uint*), uint %V
|
|
|
|
// into: %t1 = getelementptr [2 x int*]* %str, int 0, uint %V; cast
|
2005-09-13 00:40:14 +00:00
|
|
|
const Type *SrcElTy = cast<PointerType>(X->getType())->getElementType();
|
|
|
|
const Type *ResElTy=cast<PointerType>(PtrOp->getType())->getElementType();
|
|
|
|
if (isa<ArrayType>(SrcElTy) &&
|
|
|
|
TD->getTypeSize(cast<ArrayType>(SrcElTy)->getElementType()) ==
|
|
|
|
TD->getTypeSize(ResElTy)) {
|
|
|
|
Value *V = InsertNewInstBefore(
|
|
|
|
new GetElementPtrInst(X, Constant::getNullValue(Type::IntTy),
|
|
|
|
GEP.getOperand(1), GEP.getName()), GEP);
|
|
|
|
return new CastInst(V, GEP.getType());
|
2004-02-22 05:25:17 +00:00
|
|
|
}
|
2005-09-13 18:36:04 +00:00
|
|
|
|
|
|
|
// Transform things like:
|
|
|
|
// getelementptr sbyte* cast ([100 x double]* X to sbyte*), int %tmp
|
|
|
|
// (where tmp = 8*tmp2) into:
|
|
|
|
// getelementptr [100 x double]* %arr, int 0, int %tmp.2
|
|
|
|
|
|
|
|
if (isa<ArrayType>(SrcElTy) &&
|
|
|
|
(ResElTy == Type::SByteTy || ResElTy == Type::UByteTy)) {
|
|
|
|
uint64_t ArrayEltSize =
|
|
|
|
TD->getTypeSize(cast<ArrayType>(SrcElTy)->getElementType());
|
|
|
|
|
|
|
|
// Check to see if "tmp" is a scale by a multiple of ArrayEltSize. We
|
|
|
|
// allow either a mul, shift, or constant here.
|
|
|
|
Value *NewIdx = 0;
|
|
|
|
ConstantInt *Scale = 0;
|
|
|
|
if (ArrayEltSize == 1) {
|
|
|
|
NewIdx = GEP.getOperand(1);
|
|
|
|
Scale = ConstantInt::get(NewIdx->getType(), 1);
|
|
|
|
} else if (ConstantInt *CI = dyn_cast<ConstantInt>(GEP.getOperand(1))) {
|
2005-09-14 17:32:56 +00:00
|
|
|
NewIdx = ConstantInt::get(CI->getType(), 1);
|
2005-09-13 18:36:04 +00:00
|
|
|
Scale = CI;
|
|
|
|
} else if (Instruction *Inst =dyn_cast<Instruction>(GEP.getOperand(1))){
|
|
|
|
if (Inst->getOpcode() == Instruction::Shl &&
|
|
|
|
isa<ConstantInt>(Inst->getOperand(1))) {
|
|
|
|
unsigned ShAmt =cast<ConstantUInt>(Inst->getOperand(1))->getValue();
|
|
|
|
if (Inst->getType()->isSigned())
|
|
|
|
Scale = ConstantSInt::get(Inst->getType(), 1ULL << ShAmt);
|
|
|
|
else
|
|
|
|
Scale = ConstantUInt::get(Inst->getType(), 1ULL << ShAmt);
|
|
|
|
NewIdx = Inst->getOperand(0);
|
|
|
|
} else if (Inst->getOpcode() == Instruction::Mul &&
|
|
|
|
isa<ConstantInt>(Inst->getOperand(1))) {
|
|
|
|
Scale = cast<ConstantInt>(Inst->getOperand(1));
|
|
|
|
NewIdx = Inst->getOperand(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the index will be to exactly the right offset with the scale taken
|
|
|
|
// out, perform the transformation.
|
|
|
|
if (Scale && Scale->getRawValue() % ArrayEltSize == 0) {
|
|
|
|
if (ConstantSInt *C = dyn_cast<ConstantSInt>(Scale))
|
|
|
|
Scale = ConstantSInt::get(C->getType(),
|
2005-09-14 17:32:56 +00:00
|
|
|
(int64_t)C->getRawValue() /
|
|
|
|
(int64_t)ArrayEltSize);
|
2005-09-13 18:36:04 +00:00
|
|
|
else
|
|
|
|
Scale = ConstantUInt::get(Scale->getType(),
|
|
|
|
Scale->getRawValue() / ArrayEltSize);
|
|
|
|
if (Scale->getRawValue() != 1) {
|
|
|
|
Constant *C = ConstantExpr::getCast(Scale, NewIdx->getType());
|
|
|
|
Instruction *Sc = BinaryOperator::createMul(NewIdx, C, "idxscale");
|
|
|
|
NewIdx = InsertNewInstBefore(Sc, GEP);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Insert the new GEP instruction.
|
|
|
|
Instruction *Idx =
|
|
|
|
new GetElementPtrInst(X, Constant::getNullValue(Type::IntTy),
|
|
|
|
NewIdx, GEP.getName());
|
|
|
|
Idx = InsertNewInstBefore(Idx, GEP);
|
|
|
|
return new CastInst(Idx, GEP.getType());
|
|
|
|
}
|
|
|
|
}
|
2004-02-22 05:25:17 +00:00
|
|
|
}
|
2001-12-14 16:52:21 +00:00
|
|
|
}
|
2002-08-02 19:29:35 +00:00
|
|
|
|
2001-12-14 16:52:21 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2002-11-04 16:18:53 +00:00
|
|
|
Instruction *InstCombiner::visitAllocationInst(AllocationInst &AI) {
|
|
|
|
// Convert: malloc Ty, C - where C is a constant != 1 into: malloc [C x Ty], 1
|
|
|
|
if (AI.isArrayAllocation()) // Check C != 1
|
|
|
|
if (const ConstantUInt *C = dyn_cast<ConstantUInt>(AI.getArraySize())) {
|
|
|
|
const Type *NewTy = ArrayType::get(AI.getAllocatedType(), C->getValue());
|
2002-11-09 00:49:43 +00:00
|
|
|
AllocationInst *New = 0;
|
2002-11-04 16:18:53 +00:00
|
|
|
|
|
|
|
// Create and insert the replacement instruction...
|
|
|
|
if (isa<MallocInst>(AI))
|
2005-11-05 09:21:28 +00:00
|
|
|
New = new MallocInst(NewTy, 0, AI.getAlignment(), AI.getName());
|
2002-11-09 00:49:43 +00:00
|
|
|
else {
|
|
|
|
assert(isa<AllocaInst>(AI) && "Unknown type of allocation inst!");
|
2005-11-05 09:21:28 +00:00
|
|
|
New = new AllocaInst(NewTy, 0, AI.getAlignment(), AI.getName());
|
2002-11-09 00:49:43 +00:00
|
|
|
}
|
2004-03-19 06:08:10 +00:00
|
|
|
|
|
|
|
InsertNewInstBefore(New, AI);
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2002-11-04 16:18:53 +00:00
|
|
|
// Scan to the end of the allocation instructions, to skip over a block of
|
|
|
|
// allocas if possible...
|
|
|
|
//
|
|
|
|
BasicBlock::iterator It = New;
|
|
|
|
while (isa<AllocationInst>(*It)) ++It;
|
|
|
|
|
|
|
|
// Now that I is pointing to the first non-allocation-inst in the block,
|
|
|
|
// insert our getelementptr instruction...
|
|
|
|
//
|
2005-05-04 19:10:26 +00:00
|
|
|
Value *NullIdx = Constant::getNullValue(Type::IntTy);
|
|
|
|
Value *V = new GetElementPtrInst(New, NullIdx, NullIdx,
|
|
|
|
New->getName()+".sub", It);
|
2002-11-04 16:18:53 +00:00
|
|
|
|
|
|
|
// Now make everything use the getelementptr instead of the original
|
|
|
|
// allocation.
|
2004-03-19 06:08:10 +00:00
|
|
|
return ReplaceInstUsesWith(AI, V);
|
2004-10-16 18:11:37 +00:00
|
|
|
} else if (isa<UndefValue>(AI.getArraySize())) {
|
|
|
|
return ReplaceInstUsesWith(AI, Constant::getNullValue(AI.getType()));
|
2002-11-04 16:18:53 +00:00
|
|
|
}
|
2004-03-19 06:08:10 +00:00
|
|
|
|
|
|
|
// If alloca'ing a zero byte object, replace the alloca with a null pointer.
|
|
|
|
// Note that we only do this for alloca's, because malloc should allocate and
|
|
|
|
// return a unique pointer, even for a zero byte allocation.
|
2005-04-21 23:48:37 +00:00
|
|
|
if (isa<AllocaInst>(AI) && AI.getAllocatedType()->isSized() &&
|
2004-07-02 22:55:47 +00:00
|
|
|
TD->getTypeSize(AI.getAllocatedType()) == 0)
|
2004-03-19 06:08:10 +00:00
|
|
|
return ReplaceInstUsesWith(AI, Constant::getNullValue(AI.getType()));
|
|
|
|
|
2002-11-04 16:18:53 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2003-12-07 01:24:23 +00:00
|
|
|
Instruction *InstCombiner::visitFreeInst(FreeInst &FI) {
|
|
|
|
Value *Op = FI.getOperand(0);
|
|
|
|
|
|
|
|
// Change free <ty>* (cast <ty2>* X to <ty>*) into free <ty2>* X
|
|
|
|
if (CastInst *CI = dyn_cast<CastInst>(Op))
|
|
|
|
if (isa<PointerType>(CI->getOperand(0)->getType())) {
|
|
|
|
FI.setOperand(0, CI->getOperand(0));
|
|
|
|
return &FI;
|
|
|
|
}
|
|
|
|
|
2004-10-18 02:59:09 +00:00
|
|
|
// free undef -> unreachable.
|
|
|
|
if (isa<UndefValue>(Op)) {
|
|
|
|
// Insert a new store to null because we cannot modify the CFG here.
|
|
|
|
new StoreInst(ConstantBool::True,
|
|
|
|
UndefValue::get(PointerType::get(Type::BoolTy)), &FI);
|
|
|
|
return EraseInstFromFunction(FI);
|
|
|
|
}
|
|
|
|
|
2004-02-28 04:57:37 +00:00
|
|
|
// If we have 'free null' delete the instruction. This can happen in stl code
|
|
|
|
// when lots of inlining happens.
|
2004-10-18 02:59:09 +00:00
|
|
|
if (isa<ConstantPointerNull>(Op))
|
2004-02-28 05:22:00 +00:00
|
|
|
return EraseInstFromFunction(FI);
|
2004-02-28 04:57:37 +00:00
|
|
|
|
2003-12-07 01:24:23 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-01-31 05:51:45 +00:00
|
|
|
/// InstCombineLoadCast - Fold 'load (cast P)' -> cast (load P)' when possible.
|
Factor some code to handle "load (constantexpr cast foo)" just like
"load (cast foo)". This allows us to compile C++ code like this:
class Bclass {
public: virtual int operator()() { return 666; }
};
class Dclass: public Bclass {
public: virtual int operator()() { return 667; }
} ;
int main(int argc, char** argv) {
Dclass x;
return x();
}
Into this:
int %main(int %argc, sbyte** %argv) {
entry:
call void %__main( )
ret int 667
}
Instead of this:
int %main(int %argc, sbyte** %argv) {
entry:
%x = alloca "struct.std::bad_typeid" ; <"struct.std::bad_typeid"*> [#uses=3]
call void %__main( )
%tmp.1.i.i = getelementptr "struct.std::bad_typeid"* %x, uint 0, uint 0, uint 0 ; <int (...)***> [#uses=1]
store int (...)** getelementptr ([3 x int (...)*]* %vtable for Bclass, int 0, long 2), int (...)*** %tmp.1.i.i
%tmp.3.i = getelementptr "struct.std::bad_typeid"* %x, int 0, uint 0, uint 0 ; <int (...)***> [#uses=1]
store int (...)** getelementptr ([3 x int (...)*]* %vtable for Dclass, int 0, long 2), int (...)*** %tmp.3.i
%tmp.5 = load int ("struct.std::bad_typeid"*)** cast (int (...)** getelementptr ([3 x int (...)*]* %vtable for Dclass, int 0, long 2) to int
("struct.std::bad_typeid"*)**) ; <int ("struct.std::bad_typeid"*)*> [#uses=1]
%tmp.6 = call int %tmp.5( "struct.std::bad_typeid"* %x ) ; <int> [#uses=1]
ret int %tmp.6
ret int 0
}
In order words, we now resolve the virtual function call.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@14783 91177308-0d34-0410-b5e6-96231b3b80d8
2004-07-13 01:49:43 +00:00
|
|
|
static Instruction *InstCombineLoadCast(InstCombiner &IC, LoadInst &LI) {
|
|
|
|
User *CI = cast<User>(LI.getOperand(0));
|
2005-01-31 04:50:46 +00:00
|
|
|
Value *CastOp = CI->getOperand(0);
|
Factor some code to handle "load (constantexpr cast foo)" just like
"load (cast foo)". This allows us to compile C++ code like this:
class Bclass {
public: virtual int operator()() { return 666; }
};
class Dclass: public Bclass {
public: virtual int operator()() { return 667; }
} ;
int main(int argc, char** argv) {
Dclass x;
return x();
}
Into this:
int %main(int %argc, sbyte** %argv) {
entry:
call void %__main( )
ret int 667
}
Instead of this:
int %main(int %argc, sbyte** %argv) {
entry:
%x = alloca "struct.std::bad_typeid" ; <"struct.std::bad_typeid"*> [#uses=3]
call void %__main( )
%tmp.1.i.i = getelementptr "struct.std::bad_typeid"* %x, uint 0, uint 0, uint 0 ; <int (...)***> [#uses=1]
store int (...)** getelementptr ([3 x int (...)*]* %vtable for Bclass, int 0, long 2), int (...)*** %tmp.1.i.i
%tmp.3.i = getelementptr "struct.std::bad_typeid"* %x, int 0, uint 0, uint 0 ; <int (...)***> [#uses=1]
store int (...)** getelementptr ([3 x int (...)*]* %vtable for Dclass, int 0, long 2), int (...)*** %tmp.3.i
%tmp.5 = load int ("struct.std::bad_typeid"*)** cast (int (...)** getelementptr ([3 x int (...)*]* %vtable for Dclass, int 0, long 2) to int
("struct.std::bad_typeid"*)**) ; <int ("struct.std::bad_typeid"*)*> [#uses=1]
%tmp.6 = call int %tmp.5( "struct.std::bad_typeid"* %x ) ; <int> [#uses=1]
ret int %tmp.6
ret int 0
}
In order words, we now resolve the virtual function call.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@14783 91177308-0d34-0410-b5e6-96231b3b80d8
2004-07-13 01:49:43 +00:00
|
|
|
|
|
|
|
const Type *DestPTy = cast<PointerType>(CI->getType())->getElementType();
|
2005-01-31 04:50:46 +00:00
|
|
|
if (const PointerType *SrcTy = dyn_cast<PointerType>(CastOp->getType())) {
|
Factor some code to handle "load (constantexpr cast foo)" just like
"load (cast foo)". This allows us to compile C++ code like this:
class Bclass {
public: virtual int operator()() { return 666; }
};
class Dclass: public Bclass {
public: virtual int operator()() { return 667; }
} ;
int main(int argc, char** argv) {
Dclass x;
return x();
}
Into this:
int %main(int %argc, sbyte** %argv) {
entry:
call void %__main( )
ret int 667
}
Instead of this:
int %main(int %argc, sbyte** %argv) {
entry:
%x = alloca "struct.std::bad_typeid" ; <"struct.std::bad_typeid"*> [#uses=3]
call void %__main( )
%tmp.1.i.i = getelementptr "struct.std::bad_typeid"* %x, uint 0, uint 0, uint 0 ; <int (...)***> [#uses=1]
store int (...)** getelementptr ([3 x int (...)*]* %vtable for Bclass, int 0, long 2), int (...)*** %tmp.1.i.i
%tmp.3.i = getelementptr "struct.std::bad_typeid"* %x, int 0, uint 0, uint 0 ; <int (...)***> [#uses=1]
store int (...)** getelementptr ([3 x int (...)*]* %vtable for Dclass, int 0, long 2), int (...)*** %tmp.3.i
%tmp.5 = load int ("struct.std::bad_typeid"*)** cast (int (...)** getelementptr ([3 x int (...)*]* %vtable for Dclass, int 0, long 2) to int
("struct.std::bad_typeid"*)**) ; <int ("struct.std::bad_typeid"*)*> [#uses=1]
%tmp.6 = call int %tmp.5( "struct.std::bad_typeid"* %x ) ; <int> [#uses=1]
ret int %tmp.6
ret int 0
}
In order words, we now resolve the virtual function call.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@14783 91177308-0d34-0410-b5e6-96231b3b80d8
2004-07-13 01:49:43 +00:00
|
|
|
const Type *SrcPTy = SrcTy->getElementType();
|
2005-01-31 04:50:46 +00:00
|
|
|
|
2006-04-02 05:37:12 +00:00
|
|
|
if (DestPTy->isInteger() || isa<PointerType>(DestPTy) ||
|
|
|
|
isa<PackedType>(DestPTy)) {
|
2005-01-31 04:50:46 +00:00
|
|
|
// If the source is an array, the code below will not succeed. Check to
|
|
|
|
// see if a trivial 'gep P, 0, 0' will help matters. Only do this for
|
|
|
|
// constants.
|
|
|
|
if (const ArrayType *ASrcTy = dyn_cast<ArrayType>(SrcPTy))
|
|
|
|
if (Constant *CSrc = dyn_cast<Constant>(CastOp))
|
|
|
|
if (ASrcTy->getNumElements() != 0) {
|
|
|
|
std::vector<Value*> Idxs(2, Constant::getNullValue(Type::IntTy));
|
|
|
|
CastOp = ConstantExpr::getGetElementPtr(CSrc, Idxs);
|
|
|
|
SrcTy = cast<PointerType>(CastOp->getType());
|
|
|
|
SrcPTy = SrcTy->getElementType();
|
|
|
|
}
|
|
|
|
|
2006-04-02 05:37:12 +00:00
|
|
|
if ((SrcPTy->isInteger() || isa<PointerType>(SrcPTy) ||
|
|
|
|
isa<PackedType>(SrcPTy)) &&
|
2005-03-29 06:37:47 +00:00
|
|
|
// Do not allow turning this into a load of an integer, which is then
|
|
|
|
// casted to a pointer, this pessimizes pointer analysis a lot.
|
|
|
|
(isa<PointerType>(SrcPTy) == isa<PointerType>(LI.getType())) &&
|
2005-04-21 23:48:37 +00:00
|
|
|
IC.getTargetData().getTypeSize(SrcPTy) ==
|
2005-01-31 04:50:46 +00:00
|
|
|
IC.getTargetData().getTypeSize(DestPTy)) {
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2005-01-31 04:50:46 +00:00
|
|
|
// Okay, we are casting from one integer or pointer type to another of
|
|
|
|
// the same size. Instead of casting the pointer before the load, cast
|
|
|
|
// the result of the loaded value.
|
|
|
|
Value *NewLoad = IC.InsertNewInstBefore(new LoadInst(CastOp,
|
|
|
|
CI->getName(),
|
|
|
|
LI.isVolatile()),LI);
|
|
|
|
// Now cast the result of the load.
|
|
|
|
return new CastInst(NewLoad, LI.getType());
|
|
|
|
}
|
Factor some code to handle "load (constantexpr cast foo)" just like
"load (cast foo)". This allows us to compile C++ code like this:
class Bclass {
public: virtual int operator()() { return 666; }
};
class Dclass: public Bclass {
public: virtual int operator()() { return 667; }
} ;
int main(int argc, char** argv) {
Dclass x;
return x();
}
Into this:
int %main(int %argc, sbyte** %argv) {
entry:
call void %__main( )
ret int 667
}
Instead of this:
int %main(int %argc, sbyte** %argv) {
entry:
%x = alloca "struct.std::bad_typeid" ; <"struct.std::bad_typeid"*> [#uses=3]
call void %__main( )
%tmp.1.i.i = getelementptr "struct.std::bad_typeid"* %x, uint 0, uint 0, uint 0 ; <int (...)***> [#uses=1]
store int (...)** getelementptr ([3 x int (...)*]* %vtable for Bclass, int 0, long 2), int (...)*** %tmp.1.i.i
%tmp.3.i = getelementptr "struct.std::bad_typeid"* %x, int 0, uint 0, uint 0 ; <int (...)***> [#uses=1]
store int (...)** getelementptr ([3 x int (...)*]* %vtable for Dclass, int 0, long 2), int (...)*** %tmp.3.i
%tmp.5 = load int ("struct.std::bad_typeid"*)** cast (int (...)** getelementptr ([3 x int (...)*]* %vtable for Dclass, int 0, long 2) to int
("struct.std::bad_typeid"*)**) ; <int ("struct.std::bad_typeid"*)*> [#uses=1]
%tmp.6 = call int %tmp.5( "struct.std::bad_typeid"* %x ) ; <int> [#uses=1]
ret int %tmp.6
ret int 0
}
In order words, we now resolve the virtual function call.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@14783 91177308-0d34-0410-b5e6-96231b3b80d8
2004-07-13 01:49:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2004-09-19 18:43:46 +00:00
|
|
|
/// isSafeToLoadUnconditionally - Return true if we know that executing a load
|
2004-09-19 19:18:10 +00:00
|
|
|
/// from this value cannot trap. If it is not obviously safe to load from the
|
|
|
|
/// specified pointer, we do a quick local scan of the basic block containing
|
|
|
|
/// ScanFrom, to determine if the address is already accessed.
|
|
|
|
static bool isSafeToLoadUnconditionally(Value *V, Instruction *ScanFrom) {
|
|
|
|
// If it is an alloca or global variable, it is always safe to load from.
|
|
|
|
if (isa<AllocaInst>(V) || isa<GlobalVariable>(V)) return true;
|
|
|
|
|
|
|
|
// Otherwise, be a little bit agressive by scanning the local block where we
|
|
|
|
// want to check to see if the pointer is already being loaded or stored
|
2004-09-20 06:42:58 +00:00
|
|
|
// from/to. If so, the previous load or store would have already trapped,
|
|
|
|
// so there is no harm doing an extra load (also, CSE will later eliminate
|
|
|
|
// the load entirely).
|
2004-09-19 19:18:10 +00:00
|
|
|
BasicBlock::iterator BBI = ScanFrom, E = ScanFrom->getParent()->begin();
|
|
|
|
|
2004-09-20 06:42:58 +00:00
|
|
|
while (BBI != E) {
|
2004-09-19 19:18:10 +00:00
|
|
|
--BBI;
|
|
|
|
|
|
|
|
if (LoadInst *LI = dyn_cast<LoadInst>(BBI)) {
|
|
|
|
if (LI->getOperand(0) == V) return true;
|
|
|
|
} else if (StoreInst *SI = dyn_cast<StoreInst>(BBI))
|
|
|
|
if (SI->getOperand(1) == V) return true;
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2004-09-20 06:42:58 +00:00
|
|
|
}
|
2004-09-19 19:18:10 +00:00
|
|
|
return false;
|
2004-09-19 18:43:46 +00:00
|
|
|
}
|
|
|
|
|
2003-06-26 05:06:25 +00:00
|
|
|
Instruction *InstCombiner::visitLoadInst(LoadInst &LI) {
|
|
|
|
Value *Op = LI.getOperand(0);
|
2004-01-12 04:13:56 +00:00
|
|
|
|
2005-05-01 04:24:53 +00:00
|
|
|
// load (cast X) --> cast (load X) iff safe
|
|
|
|
if (CastInst *CI = dyn_cast<CastInst>(Op))
|
|
|
|
if (Instruction *Res = InstCombineLoadCast(*this, LI))
|
|
|
|
return Res;
|
|
|
|
|
|
|
|
// None of the following transforms are legal for volatile loads.
|
|
|
|
if (LI.isVolatile()) return 0;
|
2005-09-12 22:00:15 +00:00
|
|
|
|
|
|
|
if (&LI.getParent()->front() != &LI) {
|
|
|
|
BasicBlock::iterator BBI = &LI; --BBI;
|
2005-09-12 22:21:03 +00:00
|
|
|
// If the instruction immediately before this is a store to the same
|
|
|
|
// address, do a simple form of store->load forwarding.
|
2005-09-12 22:00:15 +00:00
|
|
|
if (StoreInst *SI = dyn_cast<StoreInst>(BBI))
|
|
|
|
if (SI->getOperand(1) == LI.getOperand(0))
|
|
|
|
return ReplaceInstUsesWith(LI, SI->getOperand(0));
|
2005-09-12 22:21:03 +00:00
|
|
|
if (LoadInst *LIB = dyn_cast<LoadInst>(BBI))
|
|
|
|
if (LIB->getOperand(0) == LI.getOperand(0))
|
|
|
|
return ReplaceInstUsesWith(LI, LIB);
|
2005-09-12 22:00:15 +00:00
|
|
|
}
|
2005-05-01 04:24:53 +00:00
|
|
|
|
|
|
|
if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(Op))
|
|
|
|
if (isa<ConstantPointerNull>(GEPI->getOperand(0)) ||
|
|
|
|
isa<UndefValue>(GEPI->getOperand(0))) {
|
|
|
|
// Insert a new store to null instruction before the load to indicate
|
|
|
|
// that this code is not reachable. We do this instead of inserting
|
|
|
|
// an unreachable instruction directly because we cannot modify the
|
|
|
|
// CFG.
|
|
|
|
new StoreInst(UndefValue::get(LI.getType()),
|
|
|
|
Constant::getNullValue(Op->getType()), &LI);
|
|
|
|
return ReplaceInstUsesWith(LI, UndefValue::get(LI.getType()));
|
|
|
|
}
|
|
|
|
|
2004-10-16 18:11:37 +00:00
|
|
|
if (Constant *C = dyn_cast<Constant>(Op)) {
|
2005-05-01 04:24:53 +00:00
|
|
|
// load null/undef -> undef
|
|
|
|
if ((C->isNullValue() || isa<UndefValue>(C))) {
|
2004-10-18 02:59:09 +00:00
|
|
|
// Insert a new store to null instruction before the load to indicate that
|
|
|
|
// this code is not reachable. We do this instead of inserting an
|
|
|
|
// unreachable instruction directly because we cannot modify the CFG.
|
2005-05-01 04:24:53 +00:00
|
|
|
new StoreInst(UndefValue::get(LI.getType()),
|
|
|
|
Constant::getNullValue(Op->getType()), &LI);
|
2004-10-16 18:11:37 +00:00
|
|
|
return ReplaceInstUsesWith(LI, UndefValue::get(LI.getType()));
|
2004-10-18 02:59:09 +00:00
|
|
|
}
|
2003-06-26 05:06:25 +00:00
|
|
|
|
2004-10-16 18:11:37 +00:00
|
|
|
// Instcombine load (constant global) into the value loaded.
|
|
|
|
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Op))
|
|
|
|
if (GV->isConstant() && !GV->isExternal())
|
|
|
|
return ReplaceInstUsesWith(LI, GV->getInitializer());
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2004-10-16 18:11:37 +00:00
|
|
|
// Instcombine load (constantexpr_GEP global, 0, ...) into the value loaded.
|
|
|
|
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Op))
|
|
|
|
if (CE->getOpcode() == Instruction::GetElementPtr) {
|
|
|
|
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(CE->getOperand(0)))
|
|
|
|
if (GV->isConstant() && !GV->isExternal())
|
2005-09-26 05:28:06 +00:00
|
|
|
if (Constant *V =
|
|
|
|
ConstantFoldLoadThroughGEPConstantExpr(GV->getInitializer(), CE))
|
2004-10-16 18:11:37 +00:00
|
|
|
return ReplaceInstUsesWith(LI, V);
|
2005-05-01 04:24:53 +00:00
|
|
|
if (CE->getOperand(0)->isNullValue()) {
|
|
|
|
// Insert a new store to null instruction before the load to indicate
|
|
|
|
// that this code is not reachable. We do this instead of inserting
|
|
|
|
// an unreachable instruction directly because we cannot modify the
|
|
|
|
// CFG.
|
|
|
|
new StoreInst(UndefValue::get(LI.getType()),
|
|
|
|
Constant::getNullValue(Op->getType()), &LI);
|
|
|
|
return ReplaceInstUsesWith(LI, UndefValue::get(LI.getType()));
|
|
|
|
}
|
|
|
|
|
2004-10-16 18:11:37 +00:00
|
|
|
} else if (CE->getOpcode() == Instruction::Cast) {
|
|
|
|
if (Instruction *Res = InstCombineLoadCast(*this, LI))
|
|
|
|
return Res;
|
|
|
|
}
|
|
|
|
}
|
2004-04-08 20:39:49 +00:00
|
|
|
|
2005-05-01 04:24:53 +00:00
|
|
|
if (Op->hasOneUse()) {
|
2004-09-19 18:43:46 +00:00
|
|
|
// Change select and PHI nodes to select values instead of addresses: this
|
|
|
|
// helps alias analysis out a lot, allows many others simplifications, and
|
|
|
|
// exposes redundancy in the code.
|
|
|
|
//
|
|
|
|
// Note that we cannot do the transformation unless we know that the
|
|
|
|
// introduced loads cannot trap! Something like this is valid as long as
|
|
|
|
// the condition is always false: load (select bool %C, int* null, int* %G),
|
|
|
|
// but it would not be valid if we transformed it to load from null
|
|
|
|
// unconditionally.
|
|
|
|
//
|
|
|
|
if (SelectInst *SI = dyn_cast<SelectInst>(Op)) {
|
|
|
|
// load (select (Cond, &V1, &V2)) --> select(Cond, load &V1, load &V2).
|
2004-09-19 19:18:10 +00:00
|
|
|
if (isSafeToLoadUnconditionally(SI->getOperand(1), SI) &&
|
|
|
|
isSafeToLoadUnconditionally(SI->getOperand(2), SI)) {
|
2004-09-19 18:43:46 +00:00
|
|
|
Value *V1 = InsertNewInstBefore(new LoadInst(SI->getOperand(1),
|
2004-09-20 10:15:10 +00:00
|
|
|
SI->getOperand(1)->getName()+".val"), LI);
|
2004-09-19 18:43:46 +00:00
|
|
|
Value *V2 = InsertNewInstBefore(new LoadInst(SI->getOperand(2),
|
2004-09-20 10:15:10 +00:00
|
|
|
SI->getOperand(2)->getName()+".val"), LI);
|
2004-09-19 18:43:46 +00:00
|
|
|
return new SelectInst(SI->getCondition(), V1, V2);
|
|
|
|
}
|
|
|
|
|
2004-09-23 15:46:00 +00:00
|
|
|
// load (select (cond, null, P)) -> load P
|
|
|
|
if (Constant *C = dyn_cast<Constant>(SI->getOperand(1)))
|
|
|
|
if (C->isNullValue()) {
|
|
|
|
LI.setOperand(0, SI->getOperand(2));
|
|
|
|
return &LI;
|
|
|
|
}
|
|
|
|
|
|
|
|
// load (select (cond, P, null)) -> load P
|
|
|
|
if (Constant *C = dyn_cast<Constant>(SI->getOperand(2)))
|
|
|
|
if (C->isNullValue()) {
|
|
|
|
LI.setOperand(0, SI->getOperand(1));
|
|
|
|
return &LI;
|
|
|
|
}
|
|
|
|
|
2004-09-19 18:43:46 +00:00
|
|
|
} else if (PHINode *PN = dyn_cast<PHINode>(Op)) {
|
|
|
|
// load (phi (&V1, &V2, &V3)) --> phi(load &V1, load &V2, load &V3)
|
2004-09-20 10:15:10 +00:00
|
|
|
bool Safe = PN->getParent() == LI.getParent();
|
|
|
|
|
|
|
|
// Scan all of the instructions between the PHI and the load to make
|
|
|
|
// sure there are no instructions that might possibly alter the value
|
|
|
|
// loaded from the PHI.
|
|
|
|
if (Safe) {
|
|
|
|
BasicBlock::iterator I = &LI;
|
|
|
|
for (--I; !isa<PHINode>(I); --I)
|
|
|
|
if (isa<StoreInst>(I) || isa<CallInst>(I)) {
|
|
|
|
Safe = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e && Safe; ++i)
|
2004-09-19 19:18:10 +00:00
|
|
|
if (!isSafeToLoadUnconditionally(PN->getIncomingValue(i),
|
2004-09-20 10:15:10 +00:00
|
|
|
PN->getIncomingBlock(i)->getTerminator()))
|
2004-09-19 18:43:46 +00:00
|
|
|
Safe = false;
|
2004-09-20 10:15:10 +00:00
|
|
|
|
2004-09-19 18:43:46 +00:00
|
|
|
if (Safe) {
|
|
|
|
// Create the PHI.
|
|
|
|
PHINode *NewPN = new PHINode(LI.getType(), PN->getName());
|
|
|
|
InsertNewInstBefore(NewPN, *PN);
|
|
|
|
std::map<BasicBlock*,Value*> LoadMap; // Don't insert duplicate loads
|
|
|
|
|
|
|
|
for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
|
|
|
|
BasicBlock *BB = PN->getIncomingBlock(i);
|
|
|
|
Value *&TheLoad = LoadMap[BB];
|
|
|
|
if (TheLoad == 0) {
|
|
|
|
Value *InVal = PN->getIncomingValue(i);
|
|
|
|
TheLoad = InsertNewInstBefore(new LoadInst(InVal,
|
|
|
|
InVal->getName()+".val"),
|
|
|
|
*BB->getTerminator());
|
|
|
|
}
|
|
|
|
NewPN->addIncoming(TheLoad, BB);
|
|
|
|
}
|
|
|
|
return ReplaceInstUsesWith(LI, NewPN);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2003-06-26 05:06:25 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2005-01-31 05:51:45 +00:00
|
|
|
/// InstCombineStoreToCast - Fold 'store V, (cast P)' -> store (cast V), P'
|
|
|
|
/// when possible.
|
|
|
|
static Instruction *InstCombineStoreToCast(InstCombiner &IC, StoreInst &SI) {
|
|
|
|
User *CI = cast<User>(SI.getOperand(1));
|
|
|
|
Value *CastOp = CI->getOperand(0);
|
|
|
|
|
|
|
|
const Type *DestPTy = cast<PointerType>(CI->getType())->getElementType();
|
|
|
|
if (const PointerType *SrcTy = dyn_cast<PointerType>(CastOp->getType())) {
|
|
|
|
const Type *SrcPTy = SrcTy->getElementType();
|
|
|
|
|
|
|
|
if (DestPTy->isInteger() || isa<PointerType>(DestPTy)) {
|
|
|
|
// If the source is an array, the code below will not succeed. Check to
|
|
|
|
// see if a trivial 'gep P, 0, 0' will help matters. Only do this for
|
|
|
|
// constants.
|
|
|
|
if (const ArrayType *ASrcTy = dyn_cast<ArrayType>(SrcPTy))
|
|
|
|
if (Constant *CSrc = dyn_cast<Constant>(CastOp))
|
|
|
|
if (ASrcTy->getNumElements() != 0) {
|
|
|
|
std::vector<Value*> Idxs(2, Constant::getNullValue(Type::IntTy));
|
|
|
|
CastOp = ConstantExpr::getGetElementPtr(CSrc, Idxs);
|
|
|
|
SrcTy = cast<PointerType>(CastOp->getType());
|
|
|
|
SrcPTy = SrcTy->getElementType();
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((SrcPTy->isInteger() || isa<PointerType>(SrcPTy)) &&
|
2005-04-21 23:48:37 +00:00
|
|
|
IC.getTargetData().getTypeSize(SrcPTy) ==
|
2005-01-31 05:51:45 +00:00
|
|
|
IC.getTargetData().getTypeSize(DestPTy)) {
|
|
|
|
|
|
|
|
// Okay, we are casting from one integer or pointer type to another of
|
|
|
|
// the same size. Instead of casting the pointer before the store, cast
|
|
|
|
// the value to be stored.
|
|
|
|
Value *NewCast;
|
|
|
|
if (Constant *C = dyn_cast<Constant>(SI.getOperand(0)))
|
|
|
|
NewCast = ConstantExpr::getCast(C, SrcPTy);
|
|
|
|
else
|
|
|
|
NewCast = IC.InsertNewInstBefore(new CastInst(SI.getOperand(0),
|
|
|
|
SrcPTy,
|
|
|
|
SI.getOperand(0)->getName()+".c"), SI);
|
|
|
|
|
|
|
|
return new StoreInst(NewCast, CastOp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2005-01-31 05:36:43 +00:00
|
|
|
Instruction *InstCombiner::visitStoreInst(StoreInst &SI) {
|
|
|
|
Value *Val = SI.getOperand(0);
|
|
|
|
Value *Ptr = SI.getOperand(1);
|
|
|
|
|
|
|
|
if (isa<UndefValue>(Ptr)) { // store X, undef -> noop (even if volatile)
|
Use EraseInstFromFunction in a few cases to put the uses of the removed
instruction onto the worklist (in case they are now dead).
Add a really trivial local DSE implementation to help out bitfield code.
We now fold this:
struct S {
unsigned char a : 1, b : 1, c : 1, d : 2, e : 3;
S();
};
S::S() : a(0), b(0), c(1), d(0), e(6) {}
to this:
void %_ZN1SC1Ev(%struct.S* %this) {
entry:
%tmp.1 = getelementptr %struct.S* %this, int 0, uint 0
store ubyte 38, ubyte* %tmp.1
ret void
}
much earlier (in gccas instead of only in gccld after DSE runs).
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@26050 91177308-0d34-0410-b5e6-96231b3b80d8
2006-02-08 03:25:32 +00:00
|
|
|
EraseInstFromFunction(SI);
|
2005-01-31 05:36:43 +00:00
|
|
|
++NumCombined;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
Use EraseInstFromFunction in a few cases to put the uses of the removed
instruction onto the worklist (in case they are now dead).
Add a really trivial local DSE implementation to help out bitfield code.
We now fold this:
struct S {
unsigned char a : 1, b : 1, c : 1, d : 2, e : 3;
S();
};
S::S() : a(0), b(0), c(1), d(0), e(6) {}
to this:
void %_ZN1SC1Ev(%struct.S* %this) {
entry:
%tmp.1 = getelementptr %struct.S* %this, int 0, uint 0
store ubyte 38, ubyte* %tmp.1
ret void
}
much earlier (in gccas instead of only in gccld after DSE runs).
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@26050 91177308-0d34-0410-b5e6-96231b3b80d8
2006-02-08 03:25:32 +00:00
|
|
|
// Do really simple DSE, to catch cases where there are several consequtive
|
|
|
|
// stores to the same location, separated by a few arithmetic operations. This
|
|
|
|
// situation often occurs with bitfield accesses.
|
|
|
|
BasicBlock::iterator BBI = &SI;
|
|
|
|
for (unsigned ScanInsts = 6; BBI != SI.getParent()->begin() && ScanInsts;
|
|
|
|
--ScanInsts) {
|
|
|
|
--BBI;
|
|
|
|
|
|
|
|
if (StoreInst *PrevSI = dyn_cast<StoreInst>(BBI)) {
|
|
|
|
// Prev store isn't volatile, and stores to the same location?
|
|
|
|
if (!PrevSI->isVolatile() && PrevSI->getOperand(1) == SI.getOperand(1)) {
|
|
|
|
++NumDeadStore;
|
|
|
|
++BBI;
|
|
|
|
EraseInstFromFunction(*PrevSI);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Don't skip over loads or things that can modify memory.
|
|
|
|
if (BBI->mayWriteToMemory() || isa<LoadInst>(BBI))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (SI.isVolatile()) return 0; // Don't hack volatile stores.
|
2005-01-31 05:36:43 +00:00
|
|
|
|
|
|
|
// store X, null -> turns into 'unreachable' in SimplifyCFG
|
|
|
|
if (isa<ConstantPointerNull>(Ptr)) {
|
|
|
|
if (!isa<UndefValue>(Val)) {
|
|
|
|
SI.setOperand(0, UndefValue::get(Val->getType()));
|
|
|
|
if (Instruction *U = dyn_cast<Instruction>(Val))
|
|
|
|
WorkList.push_back(U); // Dropped a use.
|
|
|
|
++NumCombined;
|
|
|
|
}
|
|
|
|
return 0; // Do not modify these!
|
|
|
|
}
|
|
|
|
|
|
|
|
// store undef, Ptr -> noop
|
|
|
|
if (isa<UndefValue>(Val)) {
|
Use EraseInstFromFunction in a few cases to put the uses of the removed
instruction onto the worklist (in case they are now dead).
Add a really trivial local DSE implementation to help out bitfield code.
We now fold this:
struct S {
unsigned char a : 1, b : 1, c : 1, d : 2, e : 3;
S();
};
S::S() : a(0), b(0), c(1), d(0), e(6) {}
to this:
void %_ZN1SC1Ev(%struct.S* %this) {
entry:
%tmp.1 = getelementptr %struct.S* %this, int 0, uint 0
store ubyte 38, ubyte* %tmp.1
ret void
}
much earlier (in gccas instead of only in gccld after DSE runs).
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@26050 91177308-0d34-0410-b5e6-96231b3b80d8
2006-02-08 03:25:32 +00:00
|
|
|
EraseInstFromFunction(SI);
|
2005-01-31 05:36:43 +00:00
|
|
|
++NumCombined;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2005-01-31 05:51:45 +00:00
|
|
|
// If the pointer destination is a cast, see if we can fold the cast into the
|
|
|
|
// source instead.
|
|
|
|
if (CastInst *CI = dyn_cast<CastInst>(Ptr))
|
|
|
|
if (Instruction *Res = InstCombineStoreToCast(*this, SI))
|
|
|
|
return Res;
|
|
|
|
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Ptr))
|
|
|
|
if (CE->getOpcode() == Instruction::Cast)
|
|
|
|
if (Instruction *Res = InstCombineStoreToCast(*this, SI))
|
|
|
|
return Res;
|
|
|
|
|
2005-09-12 23:23:25 +00:00
|
|
|
|
|
|
|
// If this store is the last instruction in the basic block, and if the block
|
|
|
|
// ends with an unconditional branch, try to move it to the successor block.
|
Use EraseInstFromFunction in a few cases to put the uses of the removed
instruction onto the worklist (in case they are now dead).
Add a really trivial local DSE implementation to help out bitfield code.
We now fold this:
struct S {
unsigned char a : 1, b : 1, c : 1, d : 2, e : 3;
S();
};
S::S() : a(0), b(0), c(1), d(0), e(6) {}
to this:
void %_ZN1SC1Ev(%struct.S* %this) {
entry:
%tmp.1 = getelementptr %struct.S* %this, int 0, uint 0
store ubyte 38, ubyte* %tmp.1
ret void
}
much earlier (in gccas instead of only in gccld after DSE runs).
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@26050 91177308-0d34-0410-b5e6-96231b3b80d8
2006-02-08 03:25:32 +00:00
|
|
|
BBI = &SI; ++BBI;
|
2005-09-12 23:23:25 +00:00
|
|
|
if (BranchInst *BI = dyn_cast<BranchInst>(BBI))
|
|
|
|
if (BI->isUnconditional()) {
|
|
|
|
// Check to see if the successor block has exactly two incoming edges. If
|
|
|
|
// so, see if the other predecessor contains a store to the same location.
|
|
|
|
// if so, insert a PHI node (if needed) and move the stores down.
|
|
|
|
BasicBlock *Dest = BI->getSuccessor(0);
|
|
|
|
|
|
|
|
pred_iterator PI = pred_begin(Dest);
|
|
|
|
BasicBlock *Other = 0;
|
|
|
|
if (*PI != BI->getParent())
|
|
|
|
Other = *PI;
|
|
|
|
++PI;
|
|
|
|
if (PI != pred_end(Dest)) {
|
|
|
|
if (*PI != BI->getParent())
|
|
|
|
if (Other)
|
|
|
|
Other = 0;
|
|
|
|
else
|
|
|
|
Other = *PI;
|
|
|
|
if (++PI != pred_end(Dest))
|
|
|
|
Other = 0;
|
|
|
|
}
|
|
|
|
if (Other) { // If only one other pred...
|
|
|
|
BBI = Other->getTerminator();
|
|
|
|
// Make sure this other block ends in an unconditional branch and that
|
|
|
|
// there is an instruction before the branch.
|
|
|
|
if (isa<BranchInst>(BBI) && cast<BranchInst>(BBI)->isUnconditional() &&
|
|
|
|
BBI != Other->begin()) {
|
|
|
|
--BBI;
|
|
|
|
StoreInst *OtherStore = dyn_cast<StoreInst>(BBI);
|
|
|
|
|
|
|
|
// If this instruction is a store to the same location.
|
|
|
|
if (OtherStore && OtherStore->getOperand(1) == SI.getOperand(1)) {
|
|
|
|
// Okay, we know we can perform this transformation. Insert a PHI
|
|
|
|
// node now if we need it.
|
|
|
|
Value *MergedVal = OtherStore->getOperand(0);
|
|
|
|
if (MergedVal != SI.getOperand(0)) {
|
|
|
|
PHINode *PN = new PHINode(MergedVal->getType(), "storemerge");
|
|
|
|
PN->reserveOperandSpace(2);
|
|
|
|
PN->addIncoming(SI.getOperand(0), SI.getParent());
|
|
|
|
PN->addIncoming(OtherStore->getOperand(0), Other);
|
|
|
|
MergedVal = InsertNewInstBefore(PN, Dest->front());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Advance to a place where it is safe to insert the new store and
|
|
|
|
// insert it.
|
|
|
|
BBI = Dest->begin();
|
|
|
|
while (isa<PHINode>(BBI)) ++BBI;
|
|
|
|
InsertNewInstBefore(new StoreInst(MergedVal, SI.getOperand(1),
|
|
|
|
OtherStore->isVolatile()), *BBI);
|
|
|
|
|
|
|
|
// Nuke the old stores.
|
Use EraseInstFromFunction in a few cases to put the uses of the removed
instruction onto the worklist (in case they are now dead).
Add a really trivial local DSE implementation to help out bitfield code.
We now fold this:
struct S {
unsigned char a : 1, b : 1, c : 1, d : 2, e : 3;
S();
};
S::S() : a(0), b(0), c(1), d(0), e(6) {}
to this:
void %_ZN1SC1Ev(%struct.S* %this) {
entry:
%tmp.1 = getelementptr %struct.S* %this, int 0, uint 0
store ubyte 38, ubyte* %tmp.1
ret void
}
much earlier (in gccas instead of only in gccld after DSE runs).
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@26050 91177308-0d34-0410-b5e6-96231b3b80d8
2006-02-08 03:25:32 +00:00
|
|
|
EraseInstFromFunction(SI);
|
|
|
|
EraseInstFromFunction(*OtherStore);
|
2005-09-12 23:23:25 +00:00
|
|
|
++NumCombined;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-01-31 05:36:43 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-06-04 04:46:00 +00:00
|
|
|
Instruction *InstCombiner::visitBranchInst(BranchInst &BI) {
|
|
|
|
// Change br (not X), label True, label False to: br X, label False, True
|
2005-06-18 17:37:34 +00:00
|
|
|
Value *X = 0;
|
2004-07-30 07:50:03 +00:00
|
|
|
BasicBlock *TrueDest;
|
|
|
|
BasicBlock *FalseDest;
|
|
|
|
if (match(&BI, m_Br(m_Not(m_Value(X)), TrueDest, FalseDest)) &&
|
|
|
|
!isa<Constant>(X)) {
|
|
|
|
// Swap Destinations and condition...
|
|
|
|
BI.setCondition(X);
|
|
|
|
BI.setSuccessor(0, FalseDest);
|
|
|
|
BI.setSuccessor(1, TrueDest);
|
|
|
|
return &BI;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Cannonicalize setne -> seteq
|
|
|
|
Instruction::BinaryOps Op; Value *Y;
|
|
|
|
if (match(&BI, m_Br(m_SetCond(Op, m_Value(X), m_Value(Y)),
|
|
|
|
TrueDest, FalseDest)))
|
|
|
|
if ((Op == Instruction::SetNE || Op == Instruction::SetLE ||
|
|
|
|
Op == Instruction::SetGE) && BI.getCondition()->hasOneUse()) {
|
|
|
|
SetCondInst *I = cast<SetCondInst>(BI.getCondition());
|
|
|
|
std::string Name = I->getName(); I->setName("");
|
|
|
|
Instruction::BinaryOps NewOpcode = SetCondInst::getInverseCondition(Op);
|
|
|
|
Value *NewSCC = BinaryOperator::create(NewOpcode, X, Y, Name, I);
|
2003-06-04 05:10:11 +00:00
|
|
|
// Swap Destinations and condition...
|
2004-07-30 07:50:03 +00:00
|
|
|
BI.setCondition(NewSCC);
|
2003-06-04 05:10:11 +00:00
|
|
|
BI.setSuccessor(0, FalseDest);
|
|
|
|
BI.setSuccessor(1, TrueDest);
|
2004-07-30 07:50:03 +00:00
|
|
|
removeFromWorkList(I);
|
|
|
|
I->getParent()->getInstList().erase(I);
|
|
|
|
WorkList.push_back(cast<Instruction>(NewSCC));
|
2003-06-04 05:10:11 +00:00
|
|
|
return &BI;
|
|
|
|
}
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2003-06-04 04:46:00 +00:00
|
|
|
return 0;
|
2004-07-03 00:26:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Instruction *InstCombiner::visitSwitchInst(SwitchInst &SI) {
|
|
|
|
Value *Cond = SI.getCondition();
|
|
|
|
if (Instruction *I = dyn_cast<Instruction>(Cond)) {
|
|
|
|
if (I->getOpcode() == Instruction::Add)
|
|
|
|
if (ConstantInt *AddRHS = dyn_cast<ConstantInt>(I->getOperand(1))) {
|
|
|
|
// change 'switch (X+4) case 1:' into 'switch (X) case -3'
|
|
|
|
for (unsigned i = 2, e = SI.getNumOperands(); i != e; i += 2)
|
2004-10-16 18:11:37 +00:00
|
|
|
SI.setOperand(i,ConstantExpr::getSub(cast<Constant>(SI.getOperand(i)),
|
2004-07-03 00:26:11 +00:00
|
|
|
AddRHS));
|
|
|
|
SI.setOperand(0, I->getOperand(0));
|
|
|
|
WorkList.push_back(I);
|
|
|
|
return &SI;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
2003-06-04 04:46:00 +00:00
|
|
|
}
|
2002-11-04 16:18:53 +00:00
|
|
|
|
2006-03-05 00:22:33 +00:00
|
|
|
/// CheapToScalarize - Return true if the value is cheaper to scalarize than it
|
|
|
|
/// is to leave as a vector operation.
|
|
|
|
static bool CheapToScalarize(Value *V, bool isConstant) {
|
|
|
|
if (isa<ConstantAggregateZero>(V))
|
|
|
|
return true;
|
|
|
|
if (ConstantPacked *C = dyn_cast<ConstantPacked>(V)) {
|
|
|
|
if (isConstant) return true;
|
|
|
|
// If all elts are the same, we can extract.
|
|
|
|
Constant *Op0 = C->getOperand(0);
|
|
|
|
for (unsigned i = 1; i < C->getNumOperands(); ++i)
|
|
|
|
if (C->getOperand(i) != Op0)
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
Instruction *I = dyn_cast<Instruction>(V);
|
|
|
|
if (!I) return false;
|
|
|
|
|
|
|
|
// Insert element gets simplified to the inserted element or is deleted if
|
|
|
|
// this is constant idx extract element and its a constant idx insertelt.
|
|
|
|
if (I->getOpcode() == Instruction::InsertElement && isConstant &&
|
|
|
|
isa<ConstantInt>(I->getOperand(2)))
|
|
|
|
return true;
|
|
|
|
if (I->getOpcode() == Instruction::Load && I->hasOneUse())
|
|
|
|
return true;
|
|
|
|
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(I))
|
|
|
|
if (BO->hasOneUse() &&
|
|
|
|
(CheapToScalarize(BO->getOperand(0), isConstant) ||
|
|
|
|
CheapToScalarize(BO->getOperand(1), isConstant)))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2006-03-31 23:01:56 +00:00
|
|
|
/// FindScalarElement - Given a vector and an element number, see if the scalar
|
|
|
|
/// value is already around as a register, for example if it were inserted then
|
|
|
|
/// extracted from the vector.
|
|
|
|
static Value *FindScalarElement(Value *V, unsigned EltNo) {
|
|
|
|
assert(isa<PackedType>(V->getType()) && "Not looking at a vector?");
|
|
|
|
const PackedType *PTy = cast<PackedType>(V->getType());
|
2006-04-10 23:06:36 +00:00
|
|
|
unsigned Width = PTy->getNumElements();
|
|
|
|
if (EltNo >= Width) // Out of range access.
|
2006-03-31 23:01:56 +00:00
|
|
|
return UndefValue::get(PTy->getElementType());
|
|
|
|
|
|
|
|
if (isa<UndefValue>(V))
|
|
|
|
return UndefValue::get(PTy->getElementType());
|
|
|
|
else if (isa<ConstantAggregateZero>(V))
|
|
|
|
return Constant::getNullValue(PTy->getElementType());
|
|
|
|
else if (ConstantPacked *CP = dyn_cast<ConstantPacked>(V))
|
|
|
|
return CP->getOperand(EltNo);
|
|
|
|
else if (InsertElementInst *III = dyn_cast<InsertElementInst>(V)) {
|
|
|
|
// If this is an insert to a variable element, we don't know what it is.
|
|
|
|
if (!isa<ConstantUInt>(III->getOperand(2))) return 0;
|
|
|
|
unsigned IIElt = cast<ConstantUInt>(III->getOperand(2))->getValue();
|
|
|
|
|
|
|
|
// If this is an insert to the element we are looking for, return the
|
|
|
|
// inserted value.
|
|
|
|
if (EltNo == IIElt) return III->getOperand(1);
|
|
|
|
|
|
|
|
// Otherwise, the insertelement doesn't modify the value, recurse on its
|
|
|
|
// vector input.
|
|
|
|
return FindScalarElement(III->getOperand(0), EltNo);
|
2006-04-10 23:06:36 +00:00
|
|
|
} else if (ShuffleVectorInst *SVI = dyn_cast<ShuffleVectorInst>(V)) {
|
|
|
|
if (isa<ConstantAggregateZero>(SVI->getOperand(2))) {
|
|
|
|
return FindScalarElement(SVI->getOperand(0), 0);
|
|
|
|
} else if (ConstantPacked *CP =
|
|
|
|
dyn_cast<ConstantPacked>(SVI->getOperand(2))) {
|
|
|
|
if (isa<UndefValue>(CP->getOperand(EltNo)))
|
|
|
|
return UndefValue::get(PTy->getElementType());
|
|
|
|
unsigned InEl = cast<ConstantUInt>(CP->getOperand(EltNo))->getValue();
|
|
|
|
if (InEl < Width)
|
|
|
|
return FindScalarElement(SVI->getOperand(0), InEl);
|
|
|
|
else
|
|
|
|
return FindScalarElement(SVI->getOperand(1), InEl - Width);
|
|
|
|
}
|
2006-03-31 23:01:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, we don't know.
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-01-13 22:48:06 +00:00
|
|
|
Instruction *InstCombiner::visitExtractElementInst(ExtractElementInst &EI) {
|
2006-03-31 23:01:56 +00:00
|
|
|
|
2006-03-31 18:25:14 +00:00
|
|
|
// If packed val is undef, replace extract with scalar undef.
|
|
|
|
if (isa<UndefValue>(EI.getOperand(0)))
|
|
|
|
return ReplaceInstUsesWith(EI, UndefValue::get(EI.getType()));
|
|
|
|
|
|
|
|
// If packed val is constant 0, replace extract with scalar 0.
|
|
|
|
if (isa<ConstantAggregateZero>(EI.getOperand(0)))
|
|
|
|
return ReplaceInstUsesWith(EI, Constant::getNullValue(EI.getType()));
|
|
|
|
|
2006-01-13 22:48:06 +00:00
|
|
|
if (ConstantPacked *C = dyn_cast<ConstantPacked>(EI.getOperand(0))) {
|
|
|
|
// If packed val is constant with uniform operands, replace EI
|
|
|
|
// with that operand
|
2006-03-05 00:22:33 +00:00
|
|
|
Constant *op0 = C->getOperand(0);
|
2006-01-13 22:48:06 +00:00
|
|
|
for (unsigned i = 1; i < C->getNumOperands(); ++i)
|
2006-03-05 00:22:33 +00:00
|
|
|
if (C->getOperand(i) != op0) {
|
|
|
|
op0 = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (op0)
|
|
|
|
return ReplaceInstUsesWith(EI, op0);
|
2006-01-13 22:48:06 +00:00
|
|
|
}
|
2006-03-05 00:22:33 +00:00
|
|
|
|
2006-03-31 23:01:56 +00:00
|
|
|
// If extracting a specified index from the vector, see if we can recursively
|
|
|
|
// find a previously computed scalar that was inserted into the vector.
|
2006-04-10 23:06:36 +00:00
|
|
|
if (ConstantUInt *IdxC = dyn_cast<ConstantUInt>(EI.getOperand(1))) {
|
2006-03-31 23:01:56 +00:00
|
|
|
if (Value *Elt = FindScalarElement(EI.getOperand(0), IdxC->getValue()))
|
|
|
|
return ReplaceInstUsesWith(EI, Elt);
|
2006-04-10 23:06:36 +00:00
|
|
|
}
|
2006-03-31 23:01:56 +00:00
|
|
|
|
2006-01-13 22:48:06 +00:00
|
|
|
if (Instruction *I = dyn_cast<Instruction>(EI.getOperand(0)))
|
|
|
|
if (I->hasOneUse()) {
|
|
|
|
// Push extractelement into predecessor operation if legal and
|
|
|
|
// profitable to do so
|
|
|
|
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(I)) {
|
2006-03-05 00:22:33 +00:00
|
|
|
bool isConstantElt = isa<ConstantInt>(EI.getOperand(1));
|
|
|
|
if (CheapToScalarize(BO, isConstantElt)) {
|
|
|
|
ExtractElementInst *newEI0 =
|
|
|
|
new ExtractElementInst(BO->getOperand(0), EI.getOperand(1),
|
|
|
|
EI.getName()+".lhs");
|
|
|
|
ExtractElementInst *newEI1 =
|
|
|
|
new ExtractElementInst(BO->getOperand(1), EI.getOperand(1),
|
|
|
|
EI.getName()+".rhs");
|
|
|
|
InsertNewInstBefore(newEI0, EI);
|
|
|
|
InsertNewInstBefore(newEI1, EI);
|
|
|
|
return BinaryOperator::create(BO->getOpcode(), newEI0, newEI1);
|
|
|
|
}
|
|
|
|
} else if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
|
2006-01-13 22:48:06 +00:00
|
|
|
Value *Ptr = InsertCastBefore(I->getOperand(0),
|
|
|
|
PointerType::get(EI.getType()), EI);
|
|
|
|
GetElementPtrInst *GEP =
|
|
|
|
new GetElementPtrInst(Ptr, EI.getOperand(1),
|
|
|
|
I->getName() + ".gep");
|
|
|
|
InsertNewInstBefore(GEP, EI);
|
|
|
|
return new LoadInst(GEP);
|
2006-03-05 00:22:33 +00:00
|
|
|
} else if (InsertElementInst *IE = dyn_cast<InsertElementInst>(I)) {
|
|
|
|
// Extracting the inserted element?
|
|
|
|
if (IE->getOperand(2) == EI.getOperand(1))
|
|
|
|
return ReplaceInstUsesWith(EI, IE->getOperand(1));
|
|
|
|
// If the inserted and extracted elements are constants, they must not
|
2006-03-30 22:02:40 +00:00
|
|
|
// be the same value, extract from the pre-inserted value instead.
|
|
|
|
if (isa<Constant>(IE->getOperand(2)) &&
|
|
|
|
isa<Constant>(EI.getOperand(1))) {
|
|
|
|
AddUsesToWorkList(EI);
|
|
|
|
EI.setOperand(0, IE->getOperand(0));
|
|
|
|
return &EI;
|
|
|
|
}
|
2006-01-13 22:48:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-04-16 00:51:47 +00:00
|
|
|
/// CollectSingleShuffleElements - If V is a shuffle of values that ONLY returns
|
|
|
|
/// elements from either LHS or RHS, return the shuffle mask and true.
|
|
|
|
/// Otherwise, return false.
|
|
|
|
static bool CollectSingleShuffleElements(Value *V, Value *LHS, Value *RHS,
|
|
|
|
std::vector<Constant*> &Mask) {
|
|
|
|
assert(V->getType() == LHS->getType() && V->getType() == RHS->getType() &&
|
|
|
|
"Invalid CollectSingleShuffleElements");
|
|
|
|
unsigned NumElts = cast<PackedType>(V->getType())->getNumElements();
|
|
|
|
|
|
|
|
if (isa<UndefValue>(V)) {
|
|
|
|
Mask.assign(NumElts, UndefValue::get(Type::UIntTy));
|
|
|
|
return true;
|
|
|
|
} else if (V == LHS) {
|
|
|
|
for (unsigned i = 0; i != NumElts; ++i)
|
|
|
|
Mask.push_back(ConstantUInt::get(Type::UIntTy, i));
|
|
|
|
return true;
|
|
|
|
} else if (V == RHS) {
|
|
|
|
for (unsigned i = 0; i != NumElts; ++i)
|
|
|
|
Mask.push_back(ConstantUInt::get(Type::UIntTy, i+NumElts));
|
|
|
|
return true;
|
|
|
|
} else if (InsertElementInst *IEI = dyn_cast<InsertElementInst>(V)) {
|
|
|
|
// If this is an insert of an extract from some other vector, include it.
|
|
|
|
Value *VecOp = IEI->getOperand(0);
|
|
|
|
Value *ScalarOp = IEI->getOperand(1);
|
|
|
|
Value *IdxOp = IEI->getOperand(2);
|
|
|
|
|
2006-04-27 21:14:21 +00:00
|
|
|
if (!isa<ConstantInt>(IdxOp))
|
|
|
|
return false;
|
|
|
|
unsigned InsertedIdx = cast<ConstantInt>(IdxOp)->getRawValue();
|
|
|
|
|
|
|
|
if (isa<UndefValue>(ScalarOp)) { // inserting undef into vector.
|
|
|
|
// Okay, we can handle this if the vector we are insertinting into is
|
|
|
|
// transitively ok.
|
|
|
|
if (CollectSingleShuffleElements(VecOp, LHS, RHS, Mask)) {
|
|
|
|
// If so, update the mask to reflect the inserted undef.
|
|
|
|
Mask[InsertedIdx] = UndefValue::get(Type::UIntTy);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
} else if (ExtractElementInst *EI = dyn_cast<ExtractElementInst>(ScalarOp)){
|
|
|
|
if (isa<ConstantInt>(EI->getOperand(1)) &&
|
2006-04-16 00:51:47 +00:00
|
|
|
EI->getOperand(0)->getType() == V->getType()) {
|
|
|
|
unsigned ExtractedIdx =
|
|
|
|
cast<ConstantInt>(EI->getOperand(1))->getRawValue();
|
|
|
|
|
|
|
|
// This must be extracting from either LHS or RHS.
|
|
|
|
if (EI->getOperand(0) == LHS || EI->getOperand(0) == RHS) {
|
|
|
|
// Okay, we can handle this if the vector we are insertinting into is
|
|
|
|
// transitively ok.
|
|
|
|
if (CollectSingleShuffleElements(VecOp, LHS, RHS, Mask)) {
|
|
|
|
// If so, update the mask to reflect the inserted value.
|
|
|
|
if (EI->getOperand(0) == LHS) {
|
|
|
|
Mask[InsertedIdx & (NumElts-1)] =
|
|
|
|
ConstantUInt::get(Type::UIntTy, ExtractedIdx);
|
|
|
|
} else {
|
|
|
|
assert(EI->getOperand(0) == RHS);
|
|
|
|
Mask[InsertedIdx & (NumElts-1)] =
|
|
|
|
ConstantUInt::get(Type::UIntTy, ExtractedIdx+NumElts);
|
|
|
|
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// TODO: Handle shufflevector here!
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// CollectShuffleElements - We are building a shuffle of V, using RHS as the
|
|
|
|
/// RHS of the shuffle instruction, if it is not null. Return a shuffle mask
|
|
|
|
/// that computes V and the LHS value of the shuffle.
|
2006-04-15 01:39:45 +00:00
|
|
|
static Value *CollectShuffleElements(Value *V, std::vector<Constant*> &Mask,
|
2006-04-16 00:51:47 +00:00
|
|
|
Value *&RHS) {
|
|
|
|
assert(isa<PackedType>(V->getType()) &&
|
|
|
|
(RHS == 0 || V->getType() == RHS->getType()) &&
|
2006-04-15 01:39:45 +00:00
|
|
|
"Invalid shuffle!");
|
|
|
|
unsigned NumElts = cast<PackedType>(V->getType())->getNumElements();
|
|
|
|
|
|
|
|
if (isa<UndefValue>(V)) {
|
|
|
|
Mask.assign(NumElts, UndefValue::get(Type::UIntTy));
|
|
|
|
return V;
|
|
|
|
} else if (isa<ConstantAggregateZero>(V)) {
|
|
|
|
Mask.assign(NumElts, ConstantUInt::get(Type::UIntTy, 0));
|
|
|
|
return V;
|
|
|
|
} else if (InsertElementInst *IEI = dyn_cast<InsertElementInst>(V)) {
|
|
|
|
// If this is an insert of an extract from some other vector, include it.
|
|
|
|
Value *VecOp = IEI->getOperand(0);
|
|
|
|
Value *ScalarOp = IEI->getOperand(1);
|
|
|
|
Value *IdxOp = IEI->getOperand(2);
|
|
|
|
|
|
|
|
if (ExtractElementInst *EI = dyn_cast<ExtractElementInst>(ScalarOp)) {
|
|
|
|
if (isa<ConstantInt>(EI->getOperand(1)) && isa<ConstantInt>(IdxOp) &&
|
|
|
|
EI->getOperand(0)->getType() == V->getType()) {
|
|
|
|
unsigned ExtractedIdx =
|
|
|
|
cast<ConstantInt>(EI->getOperand(1))->getRawValue();
|
|
|
|
unsigned InsertedIdx = cast<ConstantInt>(IdxOp)->getRawValue();
|
|
|
|
|
|
|
|
// Either the extracted from or inserted into vector must be RHSVec,
|
|
|
|
// otherwise we'd end up with a shuffle of three inputs.
|
2006-04-16 00:51:47 +00:00
|
|
|
if (EI->getOperand(0) == RHS || RHS == 0) {
|
|
|
|
RHS = EI->getOperand(0);
|
|
|
|
Value *V = CollectShuffleElements(VecOp, Mask, RHS);
|
2006-04-15 01:39:45 +00:00
|
|
|
Mask[InsertedIdx & (NumElts-1)] =
|
|
|
|
ConstantUInt::get(Type::UIntTy, NumElts+ExtractedIdx);
|
|
|
|
return V;
|
|
|
|
}
|
|
|
|
|
2006-04-16 00:51:47 +00:00
|
|
|
if (VecOp == RHS) {
|
|
|
|
Value *V = CollectShuffleElements(EI->getOperand(0), Mask, RHS);
|
2006-04-15 01:39:45 +00:00
|
|
|
// Everything but the extracted element is replaced with the RHS.
|
|
|
|
for (unsigned i = 0; i != NumElts; ++i) {
|
|
|
|
if (i != InsertedIdx)
|
|
|
|
Mask[i] = ConstantUInt::get(Type::UIntTy, NumElts+i);
|
|
|
|
}
|
|
|
|
return V;
|
|
|
|
}
|
2006-04-16 00:51:47 +00:00
|
|
|
|
|
|
|
// If this insertelement is a chain that comes from exactly these two
|
|
|
|
// vectors, return the vector and the effective shuffle.
|
|
|
|
if (CollectSingleShuffleElements(IEI, EI->getOperand(0), RHS, Mask))
|
|
|
|
return EI->getOperand(0);
|
|
|
|
|
2006-04-15 01:39:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2006-04-16 00:51:47 +00:00
|
|
|
// TODO: Handle shufflevector here!
|
2006-04-15 01:39:45 +00:00
|
|
|
|
|
|
|
// Otherwise, can't do anything fancy. Return an identity vector.
|
|
|
|
for (unsigned i = 0; i != NumElts; ++i)
|
|
|
|
Mask.push_back(ConstantUInt::get(Type::UIntTy, i));
|
|
|
|
return V;
|
|
|
|
}
|
|
|
|
|
|
|
|
Instruction *InstCombiner::visitInsertElementInst(InsertElementInst &IE) {
|
|
|
|
Value *VecOp = IE.getOperand(0);
|
|
|
|
Value *ScalarOp = IE.getOperand(1);
|
|
|
|
Value *IdxOp = IE.getOperand(2);
|
|
|
|
|
|
|
|
// If the inserted element was extracted from some other vector, and if the
|
|
|
|
// indexes are constant, try to turn this into a shufflevector operation.
|
|
|
|
if (ExtractElementInst *EI = dyn_cast<ExtractElementInst>(ScalarOp)) {
|
|
|
|
if (isa<ConstantInt>(EI->getOperand(1)) && isa<ConstantInt>(IdxOp) &&
|
|
|
|
EI->getOperand(0)->getType() == IE.getType()) {
|
|
|
|
unsigned NumVectorElts = IE.getType()->getNumElements();
|
|
|
|
unsigned ExtractedIdx=cast<ConstantInt>(EI->getOperand(1))->getRawValue();
|
|
|
|
unsigned InsertedIdx = cast<ConstantInt>(IdxOp)->getRawValue();
|
|
|
|
|
|
|
|
if (ExtractedIdx >= NumVectorElts) // Out of range extract.
|
|
|
|
return ReplaceInstUsesWith(IE, VecOp);
|
|
|
|
|
|
|
|
if (InsertedIdx >= NumVectorElts) // Out of range insert.
|
|
|
|
return ReplaceInstUsesWith(IE, UndefValue::get(IE.getType()));
|
|
|
|
|
|
|
|
// If we are extracting a value from a vector, then inserting it right
|
|
|
|
// back into the same place, just use the input vector.
|
|
|
|
if (EI->getOperand(0) == VecOp && ExtractedIdx == InsertedIdx)
|
|
|
|
return ReplaceInstUsesWith(IE, VecOp);
|
|
|
|
|
|
|
|
// We could theoretically do this for ANY input. However, doing so could
|
|
|
|
// turn chains of insertelement instructions into a chain of shufflevector
|
|
|
|
// instructions, and right now we do not merge shufflevectors. As such,
|
|
|
|
// only do this in a situation where it is clear that there is benefit.
|
|
|
|
if (isa<UndefValue>(VecOp) || isa<ConstantAggregateZero>(VecOp)) {
|
|
|
|
// Turn this into shuffle(EIOp0, VecOp, Mask). The result has all of
|
|
|
|
// the values of VecOp, except then one read from EIOp0.
|
|
|
|
// Build a new shuffle mask.
|
|
|
|
std::vector<Constant*> Mask;
|
|
|
|
if (isa<UndefValue>(VecOp))
|
|
|
|
Mask.assign(NumVectorElts, UndefValue::get(Type::UIntTy));
|
|
|
|
else {
|
|
|
|
assert(isa<ConstantAggregateZero>(VecOp) && "Unknown thing");
|
|
|
|
Mask.assign(NumVectorElts, ConstantUInt::get(Type::UIntTy,
|
|
|
|
NumVectorElts));
|
|
|
|
}
|
|
|
|
Mask[InsertedIdx] = ConstantUInt::get(Type::UIntTy, ExtractedIdx);
|
|
|
|
return new ShuffleVectorInst(EI->getOperand(0), VecOp,
|
|
|
|
ConstantPacked::get(Mask));
|
|
|
|
}
|
|
|
|
|
|
|
|
// If this insertelement isn't used by some other insertelement, turn it
|
|
|
|
// (and any insertelements it points to), into one big shuffle.
|
|
|
|
if (!IE.hasOneUse() || !isa<InsertElementInst>(IE.use_back())) {
|
|
|
|
std::vector<Constant*> Mask;
|
2006-04-16 00:51:47 +00:00
|
|
|
Value *RHS = 0;
|
|
|
|
Value *LHS = CollectShuffleElements(&IE, Mask, RHS);
|
|
|
|
if (RHS == 0) RHS = UndefValue::get(LHS->getType());
|
|
|
|
// We now have a shuffle of LHS, RHS, Mask.
|
|
|
|
return new ShuffleVectorInst(LHS, RHS, ConstantPacked::get(Mask));
|
2006-04-15 01:39:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-04-10 22:45:52 +00:00
|
|
|
Instruction *InstCombiner::visitShuffleVectorInst(ShuffleVectorInst &SVI) {
|
|
|
|
Value *LHS = SVI.getOperand(0);
|
|
|
|
Value *RHS = SVI.getOperand(1);
|
|
|
|
Constant *Mask = cast<Constant>(SVI.getOperand(2));
|
|
|
|
|
|
|
|
bool MadeChange = false;
|
|
|
|
|
|
|
|
if (isa<UndefValue>(Mask))
|
|
|
|
return ReplaceInstUsesWith(SVI, UndefValue::get(SVI.getType()));
|
|
|
|
|
2006-04-15 01:39:45 +00:00
|
|
|
// TODO: If we have shuffle(x, undef, mask) and any elements of mask refer to
|
|
|
|
// the undef, change them to undefs.
|
|
|
|
|
2006-04-10 22:45:52 +00:00
|
|
|
// Canonicalize shuffle(x,x) -> shuffle(x,undef)
|
|
|
|
if (LHS == RHS) {
|
|
|
|
if (isa<UndefValue>(LHS)) {
|
|
|
|
// shuffle(undef,undef,mask) -> undef.
|
|
|
|
return ReplaceInstUsesWith(SVI, LHS);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!isa<ConstantAggregateZero>(Mask)) {
|
|
|
|
// Remap any references to RHS to use LHS.
|
|
|
|
ConstantPacked *CP = cast<ConstantPacked>(Mask);
|
|
|
|
std::vector<Constant*> Elts;
|
|
|
|
for (unsigned i = 0, e = CP->getNumOperands(); i != e; ++i) {
|
|
|
|
Elts.push_back(CP->getOperand(i));
|
|
|
|
if (isa<UndefValue>(CP->getOperand(i)))
|
|
|
|
continue;
|
|
|
|
unsigned MV = cast<ConstantInt>(CP->getOperand(i))->getRawValue();
|
|
|
|
if (MV >= e)
|
|
|
|
Elts.back() = ConstantUInt::get(Type::UIntTy, MV & (e-1));
|
|
|
|
}
|
|
|
|
Mask = ConstantPacked::get(Elts);
|
|
|
|
}
|
|
|
|
SVI.setOperand(1, UndefValue::get(RHS->getType()));
|
|
|
|
SVI.setOperand(2, Mask);
|
|
|
|
MadeChange = true;
|
|
|
|
}
|
|
|
|
|
2006-04-16 00:03:56 +00:00
|
|
|
// Canonicalize shuffle(undef,x,mask) -> shuffle(x, undef,mask').
|
|
|
|
if (isa<UndefValue>(LHS)) {
|
|
|
|
// shuffle(undef,x,<0,0,0,0>) -> undef.
|
|
|
|
if (isa<ConstantAggregateZero>(Mask))
|
|
|
|
return ReplaceInstUsesWith(SVI, UndefValue::get(SVI.getType()));
|
|
|
|
|
|
|
|
ConstantPacked *CPM = cast<ConstantPacked>(Mask);
|
|
|
|
std::vector<Constant*> Elts;
|
|
|
|
for (unsigned i = 0, e = CPM->getNumOperands(); i != e; ++i) {
|
|
|
|
if (isa<UndefValue>(CPM->getOperand(i)))
|
|
|
|
Elts.push_back(CPM->getOperand(i));
|
|
|
|
else {
|
|
|
|
unsigned EltNo = cast<ConstantUInt>(CPM->getOperand(i))->getRawValue();
|
2006-04-16 00:51:47 +00:00
|
|
|
if (EltNo >= e)
|
|
|
|
Elts.push_back(ConstantUInt::get(Type::UIntTy, EltNo-e));
|
2006-04-16 00:03:56 +00:00
|
|
|
else // Referring to the undef.
|
|
|
|
Elts.push_back(UndefValue::get(Type::UIntTy));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return new ShuffleVectorInst(RHS, LHS, ConstantPacked::get(Elts));
|
|
|
|
}
|
|
|
|
|
2006-04-10 22:45:52 +00:00
|
|
|
if (ConstantPacked *CP = dyn_cast<ConstantPacked>(Mask)) {
|
|
|
|
bool isLHSID = true, isRHSID = true;
|
|
|
|
|
|
|
|
// Analyze the shuffle.
|
|
|
|
for (unsigned i = 0, e = CP->getNumOperands(); i != e; ++i) {
|
|
|
|
if (isa<UndefValue>(CP->getOperand(i)))
|
|
|
|
continue;
|
|
|
|
unsigned MV = cast<ConstantInt>(CP->getOperand(i))->getRawValue();
|
|
|
|
|
|
|
|
// Is this an identity shuffle of the LHS value?
|
|
|
|
isLHSID &= (MV == i);
|
|
|
|
|
|
|
|
// Is this an identity shuffle of the RHS value?
|
|
|
|
isRHSID &= (MV-e == i);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Eliminate identity shuffles.
|
|
|
|
if (isLHSID) return ReplaceInstUsesWith(SVI, LHS);
|
|
|
|
if (isRHSID) return ReplaceInstUsesWith(SVI, RHS);
|
|
|
|
}
|
|
|
|
|
|
|
|
return MadeChange ? &SVI : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-01-13 22:48:06 +00:00
|
|
|
|
2002-09-02 04:59:56 +00:00
|
|
|
void InstCombiner::removeFromWorkList(Instruction *I) {
|
|
|
|
WorkList.erase(std::remove(WorkList.begin(), WorkList.end(), I),
|
|
|
|
WorkList.end());
|
|
|
|
}
|
|
|
|
|
2004-12-08 23:43:58 +00:00
|
|
|
|
|
|
|
/// TryToSinkInstruction - Try to move the specified instruction from its
|
|
|
|
/// current block into the beginning of DestBlock, which can only happen if it's
|
|
|
|
/// safe to move the instruction past all of the instructions between it and the
|
|
|
|
/// end of its block.
|
|
|
|
static bool TryToSinkInstruction(Instruction *I, BasicBlock *DestBlock) {
|
|
|
|
assert(I->hasOneUse() && "Invariants didn't hold!");
|
|
|
|
|
2005-10-27 17:13:11 +00:00
|
|
|
// Cannot move control-flow-involving, volatile loads, vaarg, etc.
|
|
|
|
if (isa<PHINode>(I) || I->mayWriteToMemory()) return false;
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2004-12-08 23:43:58 +00:00
|
|
|
// Do not sink alloca instructions out of the entry block.
|
|
|
|
if (isa<AllocaInst>(I) && I->getParent() == &DestBlock->getParent()->front())
|
|
|
|
return false;
|
|
|
|
|
2004-12-09 07:14:34 +00:00
|
|
|
// We can only sink load instructions if there is nothing between the load and
|
|
|
|
// the end of block that could change the value.
|
|
|
|
if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
|
|
|
|
for (BasicBlock::iterator Scan = LI, E = LI->getParent()->end();
|
|
|
|
Scan != E; ++Scan)
|
|
|
|
if (Scan->mayWriteToMemory())
|
|
|
|
return false;
|
|
|
|
}
|
2004-12-08 23:43:58 +00:00
|
|
|
|
|
|
|
BasicBlock::iterator InsertPos = DestBlock->begin();
|
|
|
|
while (isa<PHINode>(InsertPos)) ++InsertPos;
|
|
|
|
|
2005-08-08 19:11:57 +00:00
|
|
|
I->moveBefore(InsertPos);
|
2004-12-08 23:43:58 +00:00
|
|
|
++NumSunkInst;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2006-05-11 17:11:52 +00:00
|
|
|
/// OptimizeConstantExpr - Given a constant expression and target data layout
|
|
|
|
/// information, symbolically evaluation the constant expr to something simpler
|
|
|
|
/// if possible.
|
|
|
|
static Constant *OptimizeConstantExpr(ConstantExpr *CE, const TargetData *TD) {
|
|
|
|
if (!TD) return CE;
|
|
|
|
|
|
|
|
Constant *Ptr = CE->getOperand(0);
|
|
|
|
if (CE->getOpcode() == Instruction::GetElementPtr && Ptr->isNullValue() &&
|
|
|
|
cast<PointerType>(Ptr->getType())->getElementType()->isSized()) {
|
|
|
|
// If this is a constant expr gep that is effectively computing an
|
|
|
|
// "offsetof", fold it into 'cast int Size to T*' instead of 'gep 0, 0, 12'
|
|
|
|
bool isFoldableGEP = true;
|
|
|
|
for (unsigned i = 1, e = CE->getNumOperands(); i != e; ++i)
|
|
|
|
if (!isa<ConstantInt>(CE->getOperand(i)))
|
|
|
|
isFoldableGEP = false;
|
|
|
|
if (isFoldableGEP) {
|
|
|
|
std::vector<Value*> Ops(CE->op_begin()+1, CE->op_end());
|
|
|
|
uint64_t Offset = TD->getIndexedOffset(Ptr->getType(), Ops);
|
|
|
|
Constant *C = ConstantUInt::get(Type::ULongTy, Offset);
|
|
|
|
C = ConstantExpr::getCast(C, TD->getIntPtrType());
|
|
|
|
return ConstantExpr::getCast(C, CE->getType());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return CE;
|
|
|
|
}
|
|
|
|
|
2006-05-10 19:00:36 +00:00
|
|
|
|
|
|
|
/// AddReachableCodeToWorklist - Walk the function in depth-first order, adding
|
|
|
|
/// all reachable code to the worklist.
|
|
|
|
///
|
|
|
|
/// This has a couple of tricks to make the code faster and more powerful. In
|
|
|
|
/// particular, we constant fold and DCE instructions as we go, to avoid adding
|
|
|
|
/// them to the worklist (this significantly speeds up instcombine on code where
|
|
|
|
/// many instructions are dead or constant). Additionally, if we find a branch
|
|
|
|
/// whose condition is a known constant, we only visit the reachable successors.
|
|
|
|
///
|
|
|
|
static void AddReachableCodeToWorklist(BasicBlock *BB,
|
|
|
|
std::set<BasicBlock*> &Visited,
|
2006-05-11 17:11:52 +00:00
|
|
|
std::vector<Instruction*> &WorkList,
|
|
|
|
const TargetData *TD) {
|
2006-05-10 19:00:36 +00:00
|
|
|
// We have now visited this block! If we've already been here, bail out.
|
|
|
|
if (!Visited.insert(BB).second) return;
|
|
|
|
|
|
|
|
for (BasicBlock::iterator BBI = BB->begin(), E = BB->end(); BBI != E; ) {
|
|
|
|
Instruction *Inst = BBI++;
|
|
|
|
|
|
|
|
// DCE instruction if trivially dead.
|
|
|
|
if (isInstructionTriviallyDead(Inst)) {
|
|
|
|
++NumDeadInst;
|
|
|
|
DEBUG(std::cerr << "IC: DCE: " << *Inst);
|
|
|
|
Inst->eraseFromParent();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ConstantProp instruction if trivially constant.
|
|
|
|
if (Constant *C = ConstantFoldInstruction(Inst)) {
|
2006-05-11 17:11:52 +00:00
|
|
|
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C))
|
|
|
|
C = OptimizeConstantExpr(CE, TD);
|
2006-05-10 19:00:36 +00:00
|
|
|
DEBUG(std::cerr << "IC: ConstFold to: " << *C << " from: " << *Inst);
|
|
|
|
Inst->replaceAllUsesWith(C);
|
|
|
|
++NumConstProp;
|
|
|
|
Inst->eraseFromParent();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
WorkList.push_back(Inst);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Recursively visit successors. If this is a branch or switch on a constant,
|
|
|
|
// only visit the reachable successor.
|
|
|
|
TerminatorInst *TI = BB->getTerminator();
|
|
|
|
if (BranchInst *BI = dyn_cast<BranchInst>(TI)) {
|
|
|
|
if (BI->isConditional() && isa<ConstantBool>(BI->getCondition())) {
|
|
|
|
bool CondVal = cast<ConstantBool>(BI->getCondition())->getValue();
|
2006-05-11 17:11:52 +00:00
|
|
|
AddReachableCodeToWorklist(BI->getSuccessor(!CondVal), Visited, WorkList,
|
|
|
|
TD);
|
2006-05-10 19:00:36 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else if (SwitchInst *SI = dyn_cast<SwitchInst>(TI)) {
|
|
|
|
if (ConstantInt *Cond = dyn_cast<ConstantInt>(SI->getCondition())) {
|
|
|
|
// See if this is an explicit destination.
|
|
|
|
for (unsigned i = 1, e = SI->getNumSuccessors(); i != e; ++i)
|
|
|
|
if (SI->getCaseValue(i) == Cond) {
|
2006-05-11 17:11:52 +00:00
|
|
|
AddReachableCodeToWorklist(SI->getSuccessor(i), Visited, WorkList,TD);
|
2006-05-10 19:00:36 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise it is the default destination.
|
2006-05-11 17:11:52 +00:00
|
|
|
AddReachableCodeToWorklist(SI->getSuccessor(0), Visited, WorkList, TD);
|
2006-05-10 19:00:36 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i)
|
2006-05-11 17:11:52 +00:00
|
|
|
AddReachableCodeToWorklist(TI->getSuccessor(i), Visited, WorkList, TD);
|
2006-05-10 19:00:36 +00:00
|
|
|
}
|
|
|
|
|
2002-06-25 16:13:24 +00:00
|
|
|
bool InstCombiner::runOnFunction(Function &F) {
|
2002-04-18 17:39:14 +00:00
|
|
|
bool Changed = false;
|
2003-11-02 05:57:39 +00:00
|
|
|
TD = &getAnalysis<TargetData>();
|
2001-12-14 16:52:21 +00:00
|
|
|
|
2005-07-07 20:40:38 +00:00
|
|
|
{
|
2006-05-10 19:00:36 +00:00
|
|
|
// Do a depth-first traversal of the function, populate the worklist with
|
|
|
|
// the reachable instructions. Ignore blocks that are not reachable. Keep
|
|
|
|
// track of which blocks we visit.
|
2005-07-07 20:40:38 +00:00
|
|
|
std::set<BasicBlock*> Visited;
|
2006-05-11 17:11:52 +00:00
|
|
|
AddReachableCodeToWorklist(F.begin(), Visited, WorkList, TD);
|
2005-07-27 06:12:32 +00:00
|
|
|
|
2005-07-07 20:40:38 +00:00
|
|
|
// Do a quick scan over the function. If we find any blocks that are
|
|
|
|
// unreachable, remove any instructions inside of them. This prevents
|
|
|
|
// the instcombine code from having to deal with some bad special cases.
|
|
|
|
for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
|
|
|
|
if (!Visited.count(BB)) {
|
|
|
|
Instruction *Term = BB->getTerminator();
|
|
|
|
while (Term != BB->begin()) { // Remove instrs bottom-up
|
|
|
|
BasicBlock::iterator I = Term; --I;
|
|
|
|
|
|
|
|
DEBUG(std::cerr << "IC: DCE: " << *I);
|
|
|
|
++NumDeadInst;
|
|
|
|
|
|
|
|
if (!I->use_empty())
|
|
|
|
I->replaceAllUsesWith(UndefValue::get(I->getType()));
|
|
|
|
I->eraseFromParent();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2001-12-14 16:52:21 +00:00
|
|
|
|
|
|
|
while (!WorkList.empty()) {
|
|
|
|
Instruction *I = WorkList.back(); // Get an instruction from the worklist
|
|
|
|
WorkList.pop_back();
|
|
|
|
|
2006-05-11 17:11:52 +00:00
|
|
|
// Check to see if we can DCE the instruction.
|
2002-09-02 04:59:56 +00:00
|
|
|
if (isInstructionTriviallyDead(I)) {
|
2006-05-11 17:11:52 +00:00
|
|
|
// Add operands to the worklist.
|
2003-10-06 17:11:01 +00:00
|
|
|
if (I->getNumOperands() < 4)
|
2004-02-28 05:22:00 +00:00
|
|
|
AddUsesToWorkList(*I);
|
2002-09-02 04:59:56 +00:00
|
|
|
++NumDeadInst;
|
2003-10-06 17:11:01 +00:00
|
|
|
|
2005-01-28 19:32:01 +00:00
|
|
|
DEBUG(std::cerr << "IC: DCE: " << *I);
|
|
|
|
|
|
|
|
I->eraseFromParent();
|
2003-10-06 17:11:01 +00:00
|
|
|
removeFromWorkList(I);
|
|
|
|
continue;
|
|
|
|
}
|
2002-09-02 04:59:56 +00:00
|
|
|
|
2006-05-11 17:11:52 +00:00
|
|
|
// Instruction isn't dead, see if we can constant propagate it.
|
2002-09-02 04:59:56 +00:00
|
|
|
if (Constant *C = ConstantFoldInstruction(I)) {
|
2006-05-11 17:11:52 +00:00
|
|
|
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C))
|
|
|
|
C = OptimizeConstantExpr(CE, TD);
|
2005-01-28 19:32:01 +00:00
|
|
|
DEBUG(std::cerr << "IC: ConstFold to: " << *C << " from: " << *I);
|
|
|
|
|
2006-05-11 17:11:52 +00:00
|
|
|
// Add operands to the worklist.
|
2004-02-28 05:22:00 +00:00
|
|
|
AddUsesToWorkList(*I);
|
2002-12-05 22:41:53 +00:00
|
|
|
ReplaceInstUsesWith(*I, C);
|
|
|
|
|
2002-09-02 04:59:56 +00:00
|
|
|
++NumConstProp;
|
2006-05-10 19:00:36 +00:00
|
|
|
I->eraseFromParent();
|
2003-10-07 15:17:02 +00:00
|
|
|
removeFromWorkList(I);
|
2003-10-06 17:11:01 +00:00
|
|
|
continue;
|
2002-09-02 04:59:56 +00:00
|
|
|
}
|
2003-10-06 17:11:01 +00:00
|
|
|
|
2004-12-08 23:43:58 +00:00
|
|
|
// See if we can trivially sink this instruction to a successor basic block.
|
|
|
|
if (I->hasOneUse()) {
|
|
|
|
BasicBlock *BB = I->getParent();
|
|
|
|
BasicBlock *UserParent = cast<Instruction>(I->use_back())->getParent();
|
|
|
|
if (UserParent != BB) {
|
|
|
|
bool UserIsSuccessor = false;
|
|
|
|
// See if the user is one of our successors.
|
|
|
|
for (succ_iterator SI = succ_begin(BB), E = succ_end(BB); SI != E; ++SI)
|
|
|
|
if (*SI == UserParent) {
|
|
|
|
UserIsSuccessor = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the user is one of our immediate successors, and if that successor
|
|
|
|
// only has us as a predecessors (we'd have to split the critical edge
|
|
|
|
// otherwise), we can keep going.
|
|
|
|
if (UserIsSuccessor && !isa<PHINode>(I->use_back()) &&
|
|
|
|
next(pred_begin(UserParent)) == pred_end(UserParent))
|
|
|
|
// Okay, the CFG is simple enough, try to sink this instruction.
|
|
|
|
Changed |= TryToSinkInstruction(I, UserParent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-12-14 16:52:21 +00:00
|
|
|
// Now that we have an instruction, try combining it to simplify it...
|
2002-08-02 19:29:35 +00:00
|
|
|
if (Instruction *Result = visit(*I)) {
|
2002-05-10 15:38:35 +00:00
|
|
|
++NumCombined;
|
2002-04-18 17:39:14 +00:00
|
|
|
// Should we replace the old instruction with a new one?
|
2002-05-14 15:24:07 +00:00
|
|
|
if (Result != I) {
|
2004-03-13 23:54:27 +00:00
|
|
|
DEBUG(std::cerr << "IC: Old = " << *I
|
|
|
|
<< " New = " << *Result);
|
|
|
|
|
Be more careful about the order we put stuff onto the worklist. This allow us to
collapse this:
bool %le(int %A, int %B) {
%c1 = setgt int %A, %B
%tmp = select bool %c1, int 1, int 0
%c2 = setlt int %A, %B
%result = select bool %c2, int -1, int %tmp
%c3 = setle int %result, 0
ret bool %c3
}
into:
bool %le(int %A, int %B) {
%c3 = setle int %A, %B ; <bool> [#uses=1]
ret bool %c3
}
which is handy, because the Java FE makes these sequences all over the place.
This is tested as: test/Regression/Transforms/InstCombine/JavaCompare.ll
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@14086 91177308-0d34-0410-b5e6-96231b3b80d8
2004-06-09 05:08:07 +00:00
|
|
|
// Everything uses the new instruction now.
|
|
|
|
I->replaceAllUsesWith(Result);
|
|
|
|
|
|
|
|
// Push the new instruction and any users onto the worklist.
|
|
|
|
WorkList.push_back(Result);
|
|
|
|
AddUsersToWorkList(*Result);
|
2003-10-06 17:11:01 +00:00
|
|
|
|
|
|
|
// Move the name to the new instruction first...
|
|
|
|
std::string OldName = I->getName(); I->setName("");
|
2003-10-07 22:58:41 +00:00
|
|
|
Result->setName(OldName);
|
2003-10-06 17:11:01 +00:00
|
|
|
|
|
|
|
// Insert the new instruction into the basic block...
|
|
|
|
BasicBlock *InstParent = I->getParent();
|
2004-11-14 19:13:23 +00:00
|
|
|
BasicBlock::iterator InsertPos = I;
|
|
|
|
|
|
|
|
if (!isa<PHINode>(Result)) // If combining a PHI, don't insert
|
|
|
|
while (isa<PHINode>(InsertPos)) // middle of a block of PHIs.
|
|
|
|
++InsertPos;
|
|
|
|
|
|
|
|
InstParent->getInstList().insert(InsertPos, Result);
|
2003-10-06 17:11:01 +00:00
|
|
|
|
2004-05-01 23:27:23 +00:00
|
|
|
// Make sure that we reprocess all operands now that we reduced their
|
|
|
|
// use counts.
|
2004-05-01 23:19:52 +00:00
|
|
|
for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i)
|
|
|
|
if (Instruction *OpI = dyn_cast<Instruction>(I->getOperand(i)))
|
|
|
|
WorkList.push_back(OpI);
|
|
|
|
|
Be more careful about the order we put stuff onto the worklist. This allow us to
collapse this:
bool %le(int %A, int %B) {
%c1 = setgt int %A, %B
%tmp = select bool %c1, int 1, int 0
%c2 = setlt int %A, %B
%result = select bool %c2, int -1, int %tmp
%c3 = setle int %result, 0
ret bool %c3
}
into:
bool %le(int %A, int %B) {
%c3 = setle int %A, %B ; <bool> [#uses=1]
ret bool %c3
}
which is handy, because the Java FE makes these sequences all over the place.
This is tested as: test/Regression/Transforms/InstCombine/JavaCompare.ll
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@14086 91177308-0d34-0410-b5e6-96231b3b80d8
2004-06-09 05:08:07 +00:00
|
|
|
// Instructions can end up on the worklist more than once. Make sure
|
|
|
|
// we do not process an instruction that has been deleted.
|
|
|
|
removeFromWorkList(I);
|
2003-10-06 17:11:01 +00:00
|
|
|
|
|
|
|
// Erase the old instruction.
|
|
|
|
InstParent->getInstList().erase(I);
|
2002-06-25 16:13:24 +00:00
|
|
|
} else {
|
2004-03-13 23:54:27 +00:00
|
|
|
DEBUG(std::cerr << "IC: MOD = " << *I);
|
|
|
|
|
2002-08-02 19:29:35 +00:00
|
|
|
// If the instruction was modified, it's possible that it is now dead.
|
|
|
|
// if so, remove it.
|
2004-05-01 23:27:23 +00:00
|
|
|
if (isInstructionTriviallyDead(I)) {
|
|
|
|
// Make sure we process all operands now that we are reducing their
|
|
|
|
// use counts.
|
|
|
|
for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i)
|
|
|
|
if (Instruction *OpI = dyn_cast<Instruction>(I->getOperand(i)))
|
|
|
|
WorkList.push_back(OpI);
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2004-05-01 23:27:23 +00:00
|
|
|
// Instructions may end up in the worklist more than once. Erase all
|
2006-01-13 22:48:06 +00:00
|
|
|
// occurrences of this instruction.
|
2002-09-02 04:59:56 +00:00
|
|
|
removeFromWorkList(I);
|
2005-01-31 05:36:43 +00:00
|
|
|
I->eraseFromParent();
|
Be more careful about the order we put stuff onto the worklist. This allow us to
collapse this:
bool %le(int %A, int %B) {
%c1 = setgt int %A, %B
%tmp = select bool %c1, int 1, int 0
%c2 = setlt int %A, %B
%result = select bool %c2, int -1, int %tmp
%c3 = setle int %result, 0
ret bool %c3
}
into:
bool %le(int %A, int %B) {
%c3 = setle int %A, %B ; <bool> [#uses=1]
ret bool %c3
}
which is handy, because the Java FE makes these sequences all over the place.
This is tested as: test/Regression/Transforms/InstCombine/JavaCompare.ll
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@14086 91177308-0d34-0410-b5e6-96231b3b80d8
2004-06-09 05:08:07 +00:00
|
|
|
} else {
|
|
|
|
WorkList.push_back(Result);
|
|
|
|
AddUsersToWorkList(*Result);
|
2002-08-02 19:29:35 +00:00
|
|
|
}
|
2002-05-14 15:24:07 +00:00
|
|
|
}
|
2002-04-18 17:39:14 +00:00
|
|
|
Changed = true;
|
2001-12-14 16:52:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-04-18 17:39:14 +00:00
|
|
|
return Changed;
|
2002-02-26 21:46:54 +00:00
|
|
|
}
|
|
|
|
|
2004-07-27 17:43:21 +00:00
|
|
|
FunctionPass *llvm::createInstructionCombiningPass() {
|
2002-04-18 17:39:14 +00:00
|
|
|
return new InstCombiner();
|
2002-02-26 21:46:54 +00:00
|
|
|
}
|
2003-11-11 22:41:34 +00:00
|
|
|
|