[llvm] r180676 - Fix a XOR reassociation bug.
Shuxin Yang
shuxin.llvm at gmail.com
Sat Apr 27 11:02:12 PDT 2013
Author: shuxin_yang
Date: Sat Apr 27 13:02:12 2013
New Revision: 180676
URL: http://llvm.org/viewvc/llvm-project?rev=180676&view=rev
Log:
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
Modified:
llvm/trunk/lib/Transforms/Scalar/Reassociate.cpp
llvm/trunk/test/Transforms/Reassociate/xor_reassoc.ll
Modified: llvm/trunk/lib/Transforms/Scalar/Reassociate.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/Reassociate.cpp?rev=180676&r1=180675&r2=180676&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/Reassociate.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/Reassociate.cpp Sat Apr 27 13:02:12 2013
@@ -1195,9 +1195,6 @@ bool Reassociate::CombineXorOpnd(Instruc
if (X != Opnd2->getSymbolicPart())
return false;
- const APInt &C1 = Opnd1->getConstPart();
- const APInt &C2 = Opnd2->getConstPart();
-
// This many instruction become dead.(At least "Opnd1 ^ Opnd2" will die.)
int DeadInstNum = 1;
if (Opnd1->getValue()->hasOneUse())
@@ -1215,6 +1212,8 @@ bool Reassociate::CombineXorOpnd(Instruc
if (Opnd2->isOrExpr())
std::swap(Opnd1, Opnd2);
+ const APInt &C1 = Opnd1->getConstPart();
+ const APInt &C2 = Opnd2->getConstPart();
APInt C3((~C1) ^ C2);
// Do not increase code size!
@@ -1230,6 +1229,8 @@ bool Reassociate::CombineXorOpnd(Instruc
} else if (Opnd1->isOrExpr()) {
// 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;
// Do not increase code size
@@ -1244,6 +1245,8 @@ bool Reassociate::CombineXorOpnd(Instruc
} else {
// Xor-Rule 4: (x & c1) ^ (x & c2) = (x & (c1^c2))
//
+ const APInt &C1 = Opnd1->getConstPart();
+ const APInt &C2 = Opnd2->getConstPart();
APInt C3 = C1 ^ C2;
Res = createAndInstr(I, X, C3);
}
Modified: llvm/trunk/test/Transforms/Reassociate/xor_reassoc.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Reassociate/xor_reassoc.ll?rev=180676&r1=180675&r2=180676&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/Reassociate/xor_reassoc.ll (original)
+++ llvm/trunk/test/Transforms/Reassociate/xor_reassoc.ll Sat Apr 27 13:02:12 2013
@@ -164,3 +164,30 @@ define void @xor_bug1() {
%3 = and i64 undef, %2
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
+}
More information about the llvm-commits
mailing list