aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDuncan Sands <baldrick@free.fr>2012-06-13 12:15:56 +0000
committerDuncan Sands <baldrick@free.fr>2012-06-13 12:15:56 +0000
commitd34491f6751ae2f8daf3e857c84bcb5b06fba889 (patch)
treea9d5f9657a7a63f520da1732d6a2a78e6fd7eadc
parentee5a094ccf1f04d3fcc92ac4d2fc8a2926cbb232 (diff)
It is possible for several constants which aren't individually absorbing to
combine to the absorbing element. Thanks to nbjoerg on IRC for pointing this out. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@158399 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Transforms/Scalar/Reassociate.cpp7
-rw-r--r--test/Transforms/Reassociate/absorption.ll11
2 files changed, 17 insertions, 1 deletions
diff --git a/lib/Transforms/Scalar/Reassociate.cpp b/lib/Transforms/Scalar/Reassociate.cpp
index ed7340f7e6..66fa0744b8 100644
--- a/lib/Transforms/Scalar/Reassociate.cpp
+++ b/lib/Transforms/Scalar/Reassociate.cpp
@@ -629,8 +629,13 @@ static bool LinearizeExprTree(BinaryOperator *I,
// Add any constants back into Ops, all globbed together and reduced to having
// weight 1 for the convenience of users.
Constant *Identity = ConstantExpr::getBinOpIdentity(Opcode, I->getType());
- if (Cst && Cst != Identity)
+ if (Cst && Cst != Identity) {
+ // If combining multiple constants resulted in the absorber then the entire
+ // expression must evaluate to the absorber.
+ if (Cst == Absorber)
+ Ops.clear();
Ops.push_back(std::make_pair(Cst, APInt(Bitwidth, 1)));
+ }
// For nilpotent operations or addition there may be no operands, for example
// because the expression was "X xor X" or consisted of 2^Bitwidth additions:
diff --git a/test/Transforms/Reassociate/absorption.ll b/test/Transforms/Reassociate/absorption.ll
new file mode 100644
index 0000000000..2ccc2b5794
--- /dev/null
+++ b/test/Transforms/Reassociate/absorption.ll
@@ -0,0 +1,11 @@
+; RUN: opt -S -reassociate < %s | FileCheck %s
+
+; Check that if constants combine to an absorbing value then the expression is
+; evaluated as the absorbing value.
+define i8 @foo(i8 %x) {
+ %tmp1 = or i8 %x, 127
+ %tmp2 = or i8 %tmp1, 128
+ ret i8 %tmp2
+; CHECK: @foo
+; CHECK: ret i8 -1
+}