From c237a849e3056bd20786457d50721acb059c0200 Mon Sep 17 00:00:00 2001 From: Owen Anderson Date: Mon, 13 Sep 2010 17:59:27 +0000 Subject: [PATCH] Re-apply r113679, which was reverted in r113720, which added a paid of new instcombine transforms 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. llvm-svn: 113763 --- .../InstCombine/InstCombineAndOrXor.cpp | 36 ++++++++++++++++--- llvm/test/CodeGen/ARM/fast-isel.ll | 16 --------- llvm/test/Transforms/InstCombine/cast.ll | 24 ++++++------- llvm/test/Transforms/InstCombine/or.ll | 17 ++++++--- llvm/test/Transforms/InstCombine/xor2.ll | 2 +- 5 files changed, 57 insertions(+), 38 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index 3dc8779879d6..4f8240ac2ee9 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -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(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(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; } diff --git a/llvm/test/CodeGen/ARM/fast-isel.ll b/llvm/test/CodeGen/ARM/fast-isel.ll index d4ca55f4ae51..b3ced9c2d87a 100644 --- a/llvm/test/CodeGen/ARM/fast-isel.ll +++ b/llvm/test/CodeGen/ARM/fast-isel.ll @@ -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 diff --git a/llvm/test/Transforms/InstCombine/cast.ll b/llvm/test/Transforms/InstCombine/cast.ll index 102d2f048f1c..75478778a9d8 100644 --- a/llvm/test/Transforms/InstCombine/cast.ll +++ b/llvm/test/Transforms/InstCombine/cast.ll @@ -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 } diff --git a/llvm/test/Transforms/InstCombine/or.ll b/llvm/test/Transforms/InstCombine/or.ll index eb887ecb7baa..500cad2ad643 100644 --- a/llvm/test/Transforms/InstCombine/or.ll +++ b/llvm/test/Transforms/InstCombine/or.ll @@ -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 +} diff --git a/llvm/test/Transforms/InstCombine/xor2.ll b/llvm/test/Transforms/InstCombine/xor2.ll index 67f05efa23d4..89f00bd68475 100644 --- a/llvm/test/Transforms/InstCombine/xor2.ll +++ b/llvm/test/Transforms/InstCombine/xor2.ll @@ -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