aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Transforms
diff options
context:
space:
mode:
authorEli Friedman <eli.friedman@gmail.com>2010-01-31 04:29:12 +0000
committerEli Friedman <eli.friedman@gmail.com>2010-01-31 04:29:12 +0000
commitbe7cfa6033d9f432a30f43870705bd57db0cbd5b (patch)
tree41578dc598461df4c0ffb408a74c345108a38f02 /lib/Transforms
parent694488f4770468f03b974180631c0fbfa21b28cc (diff)
downloadexternal_llvm-be7cfa6033d9f432a30f43870705bd57db0cbd5b.zip
external_llvm-be7cfa6033d9f432a30f43870705bd57db0cbd5b.tar.gz
external_llvm-be7cfa6033d9f432a30f43870705bd57db0cbd5b.tar.bz2
Simplify/generalize the xor+add->sign-extend instcombine.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@94943 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms')
-rw-r--r--lib/Transforms/InstCombine/InstCombineAddSub.cpp54
1 files changed, 19 insertions, 35 deletions
diff --git a/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index 119b1ca..c2924ab 100644
--- a/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -121,42 +121,26 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
match(LHS, m_Xor(m_Value(XorLHS), m_ConstantInt(XorRHS)))) {
uint32_t TySizeBits = I.getType()->getScalarSizeInBits();
const APInt& RHSVal = cast<ConstantInt>(RHSC)->getValue();
-
- uint32_t Size = TySizeBits / 2;
- APInt C0080Val(APInt(TySizeBits, 1ULL).shl(Size - 1));
- APInt CFF80Val(-C0080Val);
- do {
- if (TySizeBits > Size) {
- // 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 ((RHSVal == CFF80Val && XorRHS->getValue() == C0080Val) ||
- (RHSVal == C0080Val && XorRHS->getValue() == CFF80Val)) {
- // This is a sign extend if the top bits are known zero.
- if (!MaskedValueIsZero(XorLHS,
- APInt::getHighBitsSet(TySizeBits, TySizeBits - Size)))
- Size = 0; // Not a sign ext, but can't be any others either.
- break;
- }
- }
- Size >>= 1;
- C0080Val = APIntOps::lshr(C0080Val, Size);
- CFF80Val = APIntOps::ashr(CFF80Val, Size);
- } while (Size >= 1);
-
- // FIXME: This shouldn't be necessary. When the backends can handle types
- // with funny bit widths then this switch statement should be removed. It
- // is just here to get the size of the "middle" type back up to something
- // that the back ends can handle.
- const Type *MiddleType = 0;
- switch (Size) {
- default: break;
- case 32:
- case 16:
- case 8: MiddleType = IntegerType::get(I.getContext(), Size); break;
+ unsigned ExtendAmt = 0;
+ // 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 (XorRHS->getValue() == -RHSVal) {
+ if (RHSVal.isPowerOf2())
+ ExtendAmt = TySizeBits - RHSVal.logBase2() - 1;
+ else if (XorRHS->getValue().isPowerOf2())
+ ExtendAmt = TySizeBits - XorRHS->getValue().logBase2() - 1;
}
- if (MiddleType) {
- Value *NewTrunc = Builder->CreateTrunc(XorLHS, MiddleType, "sext");
- return new SExtInst(NewTrunc, I.getType(), I.getName());
+
+ if (ExtendAmt) {
+ APInt Mask = APInt::getHighBitsSet(TySizeBits, ExtendAmt);
+ if (!MaskedValueIsZero(XorLHS, Mask))
+ ExtendAmt = 0;
+ }
+
+ if (ExtendAmt) {
+ Constant *ShAmt = ConstantInt::get(I.getType(), ExtendAmt);
+ Value *NewShl = Builder->CreateShl(XorLHS, ShAmt, "sext");
+ return BinaryOperator::CreateAShr(NewShl, ShAmt);
}
}
}