mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-19 18:24:00 +00:00
Fix a XOR reassociation bug.
When Reassociator optimize "(x | C1)" ^ "(X & C2)", it may swap the two subexpressions, however, it forgot to swap cached constants (of C1 and C2) accordingly. rdar://13739160 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@180676 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -1195,9 +1195,6 @@ bool Reassociate::CombineXorOpnd(Instruction *I, XorOpnd *Opnd1, XorOpnd *Opnd2,
|
|||||||
if (X != Opnd2->getSymbolicPart())
|
if (X != Opnd2->getSymbolicPart())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const APInt &C1 = Opnd1->getConstPart();
|
|
||||||
const APInt &C2 = Opnd2->getConstPart();
|
|
||||||
|
|
||||||
// This many instruction become dead.(At least "Opnd1 ^ Opnd2" will die.)
|
// This many instruction become dead.(At least "Opnd1 ^ Opnd2" will die.)
|
||||||
int DeadInstNum = 1;
|
int DeadInstNum = 1;
|
||||||
if (Opnd1->getValue()->hasOneUse())
|
if (Opnd1->getValue()->hasOneUse())
|
||||||
@ -1215,6 +1212,8 @@ bool Reassociate::CombineXorOpnd(Instruction *I, XorOpnd *Opnd1, XorOpnd *Opnd2,
|
|||||||
if (Opnd2->isOrExpr())
|
if (Opnd2->isOrExpr())
|
||||||
std::swap(Opnd1, Opnd2);
|
std::swap(Opnd1, Opnd2);
|
||||||
|
|
||||||
|
const APInt &C1 = Opnd1->getConstPart();
|
||||||
|
const APInt &C2 = Opnd2->getConstPart();
|
||||||
APInt C3((~C1) ^ C2);
|
APInt C3((~C1) ^ C2);
|
||||||
|
|
||||||
// Do not increase code size!
|
// Do not increase code size!
|
||||||
@ -1230,6 +1229,8 @@ bool Reassociate::CombineXorOpnd(Instruction *I, XorOpnd *Opnd1, XorOpnd *Opnd2,
|
|||||||
} else if (Opnd1->isOrExpr()) {
|
} else if (Opnd1->isOrExpr()) {
|
||||||
// Xor-Rule 3: (x | c1) ^ (x | c2) = (x & c3) ^ c3 where c3 = c1 ^ c2
|
// Xor-Rule 3: (x | c1) ^ (x | c2) = (x & c3) ^ c3 where c3 = c1 ^ c2
|
||||||
//
|
//
|
||||||
|
const APInt &C1 = Opnd1->getConstPart();
|
||||||
|
const APInt &C2 = Opnd2->getConstPart();
|
||||||
APInt C3 = C1 ^ C2;
|
APInt C3 = C1 ^ C2;
|
||||||
|
|
||||||
// Do not increase code size
|
// Do not increase code size
|
||||||
@ -1244,6 +1245,8 @@ bool Reassociate::CombineXorOpnd(Instruction *I, XorOpnd *Opnd1, XorOpnd *Opnd2,
|
|||||||
} else {
|
} else {
|
||||||
// Xor-Rule 4: (x & c1) ^ (x & c2) = (x & (c1^c2))
|
// Xor-Rule 4: (x & c1) ^ (x & c2) = (x & (c1^c2))
|
||||||
//
|
//
|
||||||
|
const APInt &C1 = Opnd1->getConstPart();
|
||||||
|
const APInt &C2 = Opnd2->getConstPart();
|
||||||
APInt C3 = C1 ^ C2;
|
APInt C3 = C1 ^ C2;
|
||||||
Res = createAndInstr(I, X, C3);
|
Res = createAndInstr(I, X, C3);
|
||||||
}
|
}
|
||||||
|
@ -164,3 +164,30 @@ define void @xor_bug1() {
|
|||||||
%3 = and i64 undef, %2
|
%3 = and i64 undef, %2
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; The bug was that when the compiler optimize "(x | c1)" ^ "(x & c2)", it may
|
||||||
|
; swap the two xor-subexpressions if they are not in canoninical order; however,
|
||||||
|
; when optimizer swaps two sub-expressions, if forgot to swap the cached value
|
||||||
|
; of c1 and c2 accordingly, hence cause the problem.
|
||||||
|
;
|
||||||
|
define i32 @xor_bug2(i32, i32, i32, i32) {
|
||||||
|
%5 = mul i32 %0, 123
|
||||||
|
%6 = add i32 %2, 24
|
||||||
|
%7 = add i32 %1, 8
|
||||||
|
%8 = and i32 %1, 3456789
|
||||||
|
%9 = or i32 %8, 4567890
|
||||||
|
%10 = and i32 %1, 543210987
|
||||||
|
%11 = or i32 %1, 891034567
|
||||||
|
%12 = and i32 %2, 255
|
||||||
|
%13 = xor i32 %9, %10
|
||||||
|
%14 = xor i32 %11, %13
|
||||||
|
%15 = xor i32 %5, %14
|
||||||
|
%16 = and i32 %3, 255
|
||||||
|
%17 = xor i32 %16, 42
|
||||||
|
%18 = add i32 %6, %7
|
||||||
|
%19 = add i32 %18, %12
|
||||||
|
%20 = add i32 %19, %15
|
||||||
|
ret i32 %20
|
||||||
|
;CHECK: @xor_bug2
|
||||||
|
;CHECK: xor i32 %5, 891034567
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user