Fix reassociate to clear optional flags, such as nsw.
authorDan Gohman <gohman@apple.com>
Wed, 2 Feb 2011 02:02:34 +0000 (02:02 +0000)
committerDan Gohman <gohman@apple.com>
Wed, 2 Feb 2011 02:02:34 +0000 (02:02 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@124712 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Value.h
lib/Transforms/Scalar/Reassociate.cpp
test/Transforms/Reassociate/optional-flags.ll [new file with mode: 0644]

index b530287829f37a1ce736f235846f6e07e5d59b60..130e2735f525b565e20d15975a178d0781bb0065 100644 (file)
@@ -252,6 +252,12 @@ public:
     return SubclassOptionalData;
   }
 
+  /// clearSubclassOptionalData - Clear the optional flags contained in
+  /// this value.
+  void clearSubclassOptionalData() {
+    SubclassOptionalData = 0;
+  }
+
   /// hasSameSubclassOptionalData - Test whether the optional flags contained
   /// in this value are equal to the optional flags in the given value.
   bool hasSameSubclassOptionalData(const Value *V) const {
index 396b329980772ecf1ddce987d50897285f7ff4b4..5df6f3725a3e3c4b0c22aff81029f6fb5b90e2d7 100644 (file)
@@ -240,6 +240,12 @@ void Reassociate::LinearizeExpr(BinaryOperator *I) {
   RHS->setOperand(0, LHS);
   I->setOperand(0, RHS);
 
+  // Conservatively clear all the optional flags, which may not hold
+  // after the reassociation.
+  I->clearSubclassOptionalData();
+  LHS->clearSubclassOptionalData();
+  RHS->clearSubclassOptionalData();
+
   ++NumLinear;
   MadeChange = true;
   DEBUG(dbgs() << "Linearized: " << *I << '\n');
@@ -341,6 +347,11 @@ void Reassociate::RewriteExprTree(BinaryOperator *I,
       DEBUG(dbgs() << "RA: " << *I << '\n');
       I->setOperand(0, Ops[i].Op);
       I->setOperand(1, Ops[i+1].Op);
+
+      // Conservatively clear all the optional flags, which may not hold
+      // after the reassociation.
+      I->clearSubclassOptionalData();
+
       DEBUG(dbgs() << "TO: " << *I << '\n');
       MadeChange = true;
       ++NumChanged;
@@ -356,6 +367,11 @@ void Reassociate::RewriteExprTree(BinaryOperator *I,
   if (I->getOperand(1) != Ops[i].Op) {
     DEBUG(dbgs() << "RA: " << *I << '\n');
     I->setOperand(1, Ops[i].Op);
+
+    // Conservatively clear all the optional flags, which may not hold
+    // after the reassociation.
+    I->clearSubclassOptionalData();
+
     DEBUG(dbgs() << "TO: " << *I << '\n');
     MadeChange = true;
     ++NumChanged;
diff --git a/test/Transforms/Reassociate/optional-flags.ll b/test/Transforms/Reassociate/optional-flags.ll
new file mode 100644 (file)
index 0000000..5ecc767
--- /dev/null
@@ -0,0 +1,22 @@
+; RUN: opt -S -reassociate < %s | FileCheck %s
+; rdar://8944681
+
+; Reassociate should clear optional flags like nsw when reassociating.
+
+; CHECK: @test0
+; CHECK: %y = add i64 %b, %a
+; CHECK: %z = add i64 %y, %c
+define i64 @test0(i64 %a, i64 %b, i64 %c) {
+  %y = add nsw i64 %c, %b
+  %z = add i64 %y, %a
+  ret i64 %z
+}
+
+; CHECK: @test1
+; CHECK: %y = add i64 %b, %a
+; CHECK: %z = add i64 %y, %c
+define i64 @test1(i64 %a, i64 %b, i64 %c) {
+  %y = add i64 %c, %b
+  %z = add nsw i64 %y, %a
+  ret i64 %z
+}