mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-03-04 05:31:51 +00:00
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
This commit is contained in:
parent
694488f477
commit
be7cfa6033
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,8 +8,8 @@ define i32 @test1(i32 %x) {
|
||||
%tmp.3 = add i32 %tmp.2, 32768 ; <i32> [#uses=1]
|
||||
ret i32 %tmp.3
|
||||
; CHECK: @test1
|
||||
; CHECK: %sext1 = shl i32 %x, 16
|
||||
; CHECK: %tmp.3 = ashr i32 %sext1, 16
|
||||
; CHECK: %sext = shl i32 %x, 16
|
||||
; CHECK: %tmp.3 = ashr i32 %sext, 16
|
||||
; CHECK: ret i32 %tmp.3
|
||||
}
|
||||
|
||||
@ -19,8 +19,8 @@ define i32 @test2(i32 %x) {
|
||||
%tmp.3 = add i32 %tmp.2, -32768 ; <i32> [#uses=1]
|
||||
ret i32 %tmp.3
|
||||
; CHECK: @test2
|
||||
; CHECK: %sext1 = shl i32 %x, 16
|
||||
; CHECK: %tmp.3 = ashr i32 %sext1, 16
|
||||
; CHECK: %sext = shl i32 %x, 16
|
||||
; CHECK: %tmp.3 = ashr i32 %sext, 16
|
||||
; CHECK: ret i32 %tmp.3
|
||||
}
|
||||
|
||||
@ -50,8 +50,8 @@ define i32 @test5(i32 %x) {
|
||||
%tmp.3 = add i32 %tmp.2, -128 ; <i32> [#uses=1]
|
||||
ret i32 %tmp.3
|
||||
; CHECK: @test5
|
||||
; CHECK: %sext1 = shl i32 %x, 24
|
||||
; CHECK: %tmp.3 = ashr i32 %sext1, 24
|
||||
; CHECK: %sext = shl i32 %x, 24
|
||||
; CHECK: %tmp.3 = ashr i32 %sext, 24
|
||||
; CHECK: ret i32 %tmp.3
|
||||
}
|
||||
|
||||
@ -74,3 +74,14 @@ define i32 @test7(i16 %P) {
|
||||
; CHECK: %tmp.5 = sext i16 %P to i32
|
||||
; CHECK: ret i32 %tmp.5
|
||||
}
|
||||
|
||||
define i32 @test8(i32 %x) nounwind readnone {
|
||||
entry:
|
||||
%shr = lshr i32 %x, 5 ; <i32> [#uses=1]
|
||||
%xor = xor i32 %shr, 67108864 ; <i32> [#uses=1]
|
||||
%sub = add i32 %xor, -67108864 ; <i32> [#uses=1]
|
||||
ret i32 %sub
|
||||
; CHECK: @test8
|
||||
; CHECK: %sub = ashr i32 %x, 5
|
||||
; CHECK: ret i32 %sub
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user