[llvm-branch-commits] [llvm] 374ef57 - [InstCombine] 'hoist xor-by-constant from xor-by-value': completely give up on constant exprs

Roman Lebedev via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Dec 29 05:33:36 PST 2020


Author: Roman Lebedev
Date: 2020-12-29T16:28:18+03:00
New Revision: 374ef57f1379d3d3bbe5bfb19f1d2ea7e79b6db9

URL: https://github.com/llvm/llvm-project/commit/374ef57f1379d3d3bbe5bfb19f1d2ea7e79b6db9
DIFF: https://github.com/llvm/llvm-project/commit/374ef57f1379d3d3bbe5bfb19f1d2ea7e79b6db9.diff

LOG: [InstCombine] 'hoist xor-by-constant from xor-by-value': completely give up on constant exprs

As Mikael Holmén is noting in the post-commit review for the first fix
https://reviews.llvm.org/rGd4ccef38d0bb#967466
not hoisting constantexprs is not enough,
because if the xor originally was a constantexpr (i.e. X is a constantexpr).
`SimplifyAssociativeOrCommutative()` in `visitXor()` will immediately
undo this transform, thus again causing an infinite combine loop.

This transform has resulted in a surprising number of constantexpr failures.

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
    llvm/test/Transforms/InstCombine/hoist-xor-by-constant-from-xor-by-value.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index c0823c950368..15dcf2d19c15 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -3459,9 +3459,11 @@ Instruction *InstCombinerImpl::visitXor(BinaryOperator &I) {
 
   // Otherwise, if all else failed, try to hoist the xor-by-constant:
   //   (X ^ C) ^ Y --> (X ^ Y) ^ C
-  // Just like we do in other places, we avoid the fold for constantexprs,
-  // at least to avoid endless combine loop.
-  if (match(&I, m_c_Xor(m_OneUse(m_Xor(m_Value(X), m_ImmConstant(C1))),
+  // Just like we do in other places, we completely avoid the fold
+  // for constantexprs, at least to avoid endless combine loop.
+  if (match(&I, m_c_Xor(m_OneUse(m_Xor(m_CombineAnd(m_Value(X),
+                                                    m_Unless(m_ConstantExpr())),
+                                       m_ImmConstant(C1))),
                         m_Value(Y))))
     return BinaryOperator::CreateXor(Builder.CreateXor(X, Y), C1);
 

diff  --git a/llvm/test/Transforms/InstCombine/hoist-xor-by-constant-from-xor-by-value.ll b/llvm/test/Transforms/InstCombine/hoist-xor-by-constant-from-xor-by-value.ll
index 14227d304df7..46bdb1a6092e 100644
--- a/llvm/test/Transforms/InstCombine/hoist-xor-by-constant-from-xor-by-value.ll
+++ b/llvm/test/Transforms/InstCombine/hoist-xor-by-constant-from-xor-by-value.ll
@@ -87,3 +87,23 @@ entry:
   %r = xor i8 %or, xor (i8 xor (i8 ptrtoint (i32* @global_constant to i8), i8 -1), i8 xor (i8 ptrtoint (i32* @global_constant2 to i8), i8 -1))
   ret i8 %r
 }
+
+ at global_constant3 = external global [6 x [1 x i64]], align 1
+ at global_constant4 = external global i64, align 1
+ at global_constant5 = external global i16*, align 1
+
+define i16 @constantexpr2() {
+; CHECK-LABEL: @constantexpr2(
+; CHECK-NEXT:    [[I2:%.*]] = load i16*, i16** @global_constant5, align 1
+; CHECK-NEXT:    [[I3:%.*]] = load i16, i16* [[I2]], align 1
+; CHECK-NEXT:    [[I5:%.*]] = xor i16 [[I3]], xor (i16 zext (i1 icmp ne (i64* getelementptr inbounds ([6 x [1 x i64]], [6 x [1 x i64]]* @global_constant3, i64 0, i64 5, i64 0), i64* @global_constant4) to i16), i16 -1)
+; CHECK-NEXT:    ret i16 [[I5]]
+;
+  %i0 = icmp ne i64* getelementptr inbounds ([6 x [1 x i64]], [6 x [1 x i64]]* @global_constant3, i16 0, i16 5, i16 0), @global_constant4
+  %i1 = zext i1 %i0 to i16
+  %i2 = load i16*, i16** @global_constant5, align 1
+  %i3 = load i16, i16* %i2, align 1
+  %i4 = xor i16 %i3, %i1
+  %i5 = xor i16 %i4, -1
+  ret i16 %i5
+}


        


More information about the llvm-branch-commits mailing list