Re-apply r113679, which was reverted in r113720, which added a paid of new instcombin...
authorOwen Anderson <resistor@mac.com>
Mon, 13 Sep 2010 17:59:27 +0000 (17:59 +0000)
committerOwen Anderson <resistor@mac.com>
Mon, 13 Sep 2010 17:59:27 +0000 (17:59 +0000)
to expose greater opportunities for store narrowing in codegen.  This patch fixes a potential
infinite loop in instcombine caused by one of the introduced transforms being overly aggressive.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@113763 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
test/CodeGen/ARM/fast-isel.ll
test/Transforms/InstCombine/cast.ll
test/Transforms/InstCombine/or.ll
test/Transforms/InstCombine/xor2.ll

index 3dc8779879d6e84ff28a92a22e39be0f14ebb157..4f8240ac2ee93a8665fc8d14152556a440d6ff86 100644 (file)
@@ -207,12 +207,26 @@ Instruction *InstCombiner::OptAndOp(Instruction *Op,
     }
     break;
   case Instruction::Or:
-    if (Op->hasOneUse() && Together != OpRHS) {
-      // (X | C1) & C2 --> (X | (C1&C2)) & C2
-      Value *Or = Builder->CreateOr(X, Together);
-      Or->takeName(Op);
-      return BinaryOperator::CreateAnd(Or, AndRHS);
+    if (Op->hasOneUse()){
+      if (Together != OpRHS) {
+        // (X | C1) & C2 --> (X | (C1&C2)) & C2
+        Value *Or = Builder->CreateOr(X, Together);
+        Or->takeName(Op);
+        return BinaryOperator::CreateAnd(Or, AndRHS);
+      }
+      
+      ConstantInt *TogetherCI = dyn_cast<ConstantInt>(Together);
+      if (TogetherCI && !TogetherCI->isZero()){
+        // (X | C1) & C2 --> (X & (C2^(C1&C2))) | C1
+        // NOTE: This reduces the number of bits set in the & mask, which
+        // can expose opportunities for store narrowing.
+        Together = ConstantExpr::getXor(AndRHS, Together);
+        Value *And = Builder->CreateAnd(X, Together);
+        And->takeName(Op);
+        return BinaryOperator::CreateOr(And, OpRHS);
+      }
     }
+    
     break;
   case Instruction::Add:
     if (Op->hasOneUse()) {
@@ -1943,6 +1957,18 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) {
       }
   }
   
+  // Note: If we've gotten to the point of visiting the outer OR, then the
+  // inner one couldn't be simplified.  If it was a constant, then it won't
+  // be simplified by a later pass either, so we try swapping the inner/outer
+  // ORs in the hopes that we'll be able to simplify it this way.
+  // (X|C) | V --> (X|V) | C
+  if (Op0->hasOneUse() && !isa<ConstantInt>(Op1) &&
+      match(Op0, m_Or(m_Value(A), m_ConstantInt(C1)))) {
+    Value *Inner = Builder->CreateOr(A, Op1);
+    Inner->takeName(Op0);
+    return BinaryOperator::CreateOr(Inner, C1);
+  }
+  
   return Changed ? &I : 0;
 }
 
index d4ca55f4ae51036fbd34167db84d7996e3db98ad..b3ced9c2d87a8d6cf31f89a7df2d6b774cd9a260 100644 (file)
@@ -15,22 +15,6 @@ entry:
   ret i32 %add
 }
 
-define float @fp_ops(float %a, float %b) nounwind {
-entry:
-  %a.addr = alloca float, align 4
-  %b.addr = alloca float, align 4
-  store float %a, float* %a.addr
-  store float %b, float* %b.addr
-  %tmp = load float* %a.addr
-  %tmp1 = load float* %b.addr
-  %mul = fmul float %tmp, %tmp1
-  %tmp2 = load float* %b.addr
-  %tmp3 = load float* %a.addr
-  %mul2 = fmul float %tmp2, %tmp3
-  %add = fadd float %mul, %mul2
-  ret float %mul
-}
-
 define i32* @foo(i32* %p, i32* %q, i32** %z) nounwind {
 entry:
   %r = load i32* %p
index 102d2f048f1c244d1faff2cf4f2e28de6860f0d8..75478778a9d8c0c23b83004d474c2b2953759007 100644 (file)
@@ -437,8 +437,8 @@ define i64 @test47(i8 %A) {
  ret i64 %E
 ; CHECK: @test47
 ; CHECK-NEXT:   %B = sext i8 %A to i64
-; CHECK-NEXT: %C = or i64 %B, 42
-; CHECK-NEXT:  %E = and i64 %C, 4294967295
+; CHECK-NEXT: %C = and i64 %B, 4294967253
+; CHECK-NEXT:  %E = or i64 %C, 42
 ; CHECK-NEXT:  ret i64 %E
 }
 
@@ -508,8 +508,8 @@ define i32 @test52(i64 %A) {
   ret i32 %E
 ; CHECK: @test52
 ; CHECK-NEXT: %B = trunc i64 %A to i32
-; CHECK-NEXT: %C = or i32 %B, 32962
-; CHECK-NEXT: %D = and i32 %C, 40186
+; CHECK-NEXT: %C = and i32 %B, 7224
+; CHECK-NEXT: %D = or i32 %C, 32962
 ; CHECK-NEXT: ret i32 %D
 }
 
@@ -521,8 +521,8 @@ define i64 @test53(i32 %A) {
   ret i64 %E
 ; CHECK: @test53
 ; CHECK-NEXT: %B = zext i32 %A to i64
-; CHECK-NEXT: %C = or i64 %B, 32962
-; CHECK-NEXT: %D = and i64 %C, 40186
+; CHECK-NEXT: %C = and i64 %B, 7224
+; CHECK-NEXT: %D = or i64 %C, 32962
 ; CHECK-NEXT: ret i64 %D
 }
 
@@ -534,8 +534,8 @@ define i32 @test54(i64 %A) {
   ret i32 %E
 ; CHECK: @test54
 ; CHECK-NEXT: %B = trunc i64 %A to i32
-; CHECK-NEXT: %C = or i32 %B, -32574
-; CHECK-NEXT: %D = and i32 %C, -25350
+; CHECK-NEXT: %C = and i32 %B, 7224
+; CHECK-NEXT: %D = or i32 %C, -32574
 ; CHECK-NEXT: ret i32 %D
 }
 
@@ -547,8 +547,8 @@ define i64 @test55(i32 %A) {
   ret i64 %E
 ; CHECK: @test55
 ; CHECK-NEXT: %B = zext i32 %A to i64
-; CHECK-NEXT: %C = or i64 %B, -32574
-; CHECK-NEXT: %D = and i64 %C, -25350
+; CHECK-NEXT: %C = and i64 %B, 7224
+; CHECK-NEXT: %D = or i64 %C, -32574
 ; CHECK-NEXT: ret i64 %D
 }
 
@@ -584,8 +584,8 @@ define i64 @test58(i64 %A) nounwind {
  
 ; CHECK: @test58
 ; CHECK-NEXT:   %C = lshr i64 %A, 8
-; CHECK-NEXT:   %D = or i64 %C, 128
-; CHECK-NEXT:   %E = and i64 %D, 16777215
+; CHECK-NEXT:   %D = and i64 %C, 16777087
+; CHECK-NEXT:   %E = or i64 %D, 128
 ; CHECK-NEXT:   ret i64 %E
 }
 
index eb887ecb7baa341c7fbe89dd7769d0016d6b0508..500cad2ad643c522e32c477bca11ce040d36ca12 100644 (file)
@@ -316,8 +316,8 @@ entry:
   %E = or i32 %D, %C
   ret i32 %E
 ; CHECK: @test30
-; CHECK: %B = or i32 %A, 32962
-; CHECK: %E = and i32 %B, -25350
+; CHECK: %D = and i32 %A, -58312
+; CHECK: %E = or i32 %D, 32962
 ; CHECK: ret i32 %E
 }
 
@@ -332,8 +332,8 @@ define i64 @test31(i64 %A) nounwind readnone ssp noredzone {
   %F = or i64 %D, %E
   ret i64 %F
 ; CHECK: @test31
-; CHECK-NEXT: %bitfield = or i64 %A, 32962
-; CHECK-NEXT: %F = and i64 %bitfield, 4294941946
+; CHECK-NEXT: %E1 = and i64 %A, 4294908984
+; CHECK-NEXT: %F = or i64 %E1, 32962
 ; CHECK-NEXT: ret i64 %F
 }
 
@@ -367,3 +367,12 @@ define i32 @test34(i32 %X, i32 %Y) {
 ; CHECK-NEXT: or i32 %X, %Y
 ; CHECK-NEXT: ret
 }
+
+define i32 @test35(i32 %a, i32 %b) {
+  %1 = or i32 %a, 1135
+  %2 = or i32 %1, %b
+  ret i32 %2
+  ; CHECK: @test35
+  ; CHECK-NEXT: or i32 %a, %b
+  ; CHECK-NEXT: or i32 %1, 1135
+}
index 67f05efa23d41371fcce111e970a2bb5403d9e68..89f00bd684757c12135f4cc6765376acdd0d733b 100644 (file)
@@ -34,7 +34,7 @@ define i32 @test2(i32 %tmp1) {
 define i32 @test3(i32 %tmp1) {
 ; CHECK:      @test3
 ; CHECK-NEXT:   and i32 %tmp1, 32
-; CHECK-NEXT:   or i32 %tmp, 8
+; CHECK-NEXT:   or i32 %ovm, 8
 ; CHECK-NEXT:   ret i32
   %ovm = or i32 %tmp1, 145 
   %ov31 = and i32 %ovm, 177