[ValueTracking] Introduce a KnownBits struct to wrap the two APInts for computeKnownBits
This patch introduces a new KnownBits struct that wraps the two APInt used by computeKnownBits. This allows us to treat them as more of a unit. Initially I've just altered the signatures of computeKnownBits and InstCombine's simplifyDemandedBits to pass a KnownBits reference instead of two separate APInt references. I'll do similar to the SelectionDAG version of computeKnownBits/simplifyDemandedBits as a separate patch. I've added a constructor that allows initializing both APInts to the same bit width with a starting value of 0. This reduces the repeated pattern of initializing both APInts. Once place default constructed the APInts so I added a default constructor for those cases. Going forward I would like to add more methods that will work on the pairs. For example trunc, zext, and sext occur on both APInts together in several places. We should probably add a clear method that can be used to clear both pieces. Maybe a method to check for conflicting information. A method to return (Zero|One) so we don't write it out everywhere. Maybe a method for (Zero|One).isAllOnesValue() to determine if all bits are known. I'm sure there are many other methods we can come up with. Differential Revision: https://reviews.llvm.org/D32376 llvm-svn: 301432
This commit is contained in:
@@ -42,6 +42,7 @@
|
||||
#include "llvm/IR/Value.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/KnownBits.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include <cassert>
|
||||
#include <cerrno>
|
||||
@@ -687,21 +688,21 @@ Constant *SymbolicallyEvaluateBinop(unsigned Opc, Constant *Op0, Constant *Op1,
|
||||
|
||||
if (Opc == Instruction::And) {
|
||||
unsigned BitWidth = DL.getTypeSizeInBits(Op0->getType()->getScalarType());
|
||||
APInt KnownZero0(BitWidth, 0), KnownOne0(BitWidth, 0);
|
||||
APInt KnownZero1(BitWidth, 0), KnownOne1(BitWidth, 0);
|
||||
computeKnownBits(Op0, KnownZero0, KnownOne0, DL);
|
||||
computeKnownBits(Op1, KnownZero1, KnownOne1, DL);
|
||||
if ((KnownOne1 | KnownZero0).isAllOnesValue()) {
|
||||
KnownBits Known0(BitWidth);
|
||||
KnownBits Known1(BitWidth);
|
||||
computeKnownBits(Op0, Known0, DL);
|
||||
computeKnownBits(Op1, Known1, DL);
|
||||
if ((Known1.One | Known0.Zero).isAllOnesValue()) {
|
||||
// All the bits of Op0 that the 'and' could be masking are already zero.
|
||||
return Op0;
|
||||
}
|
||||
if ((KnownOne0 | KnownZero1).isAllOnesValue()) {
|
||||
if ((Known0.One | Known1.Zero).isAllOnesValue()) {
|
||||
// All the bits of Op1 that the 'and' could be masking are already zero.
|
||||
return Op1;
|
||||
}
|
||||
|
||||
APInt KnownZero = KnownZero0 | KnownZero1;
|
||||
APInt KnownOne = KnownOne0 & KnownOne1;
|
||||
APInt KnownZero = Known0.Zero | Known1.Zero;
|
||||
APInt KnownOne = Known0.One & Known1.One;
|
||||
if ((KnownZero | KnownOne).isAllOnesValue()) {
|
||||
return ConstantInt::get(Op0->getType(), KnownOne);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user