mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-10-31 08:16:47 +00:00 
			
		
		
		
	optimize:
void a(int x) { if (((1<<x)&8)==0) b(); }
into "x != 3", which occurs over 100 times in 403.gcc but in no
other program in llvm-test.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@119922 91177308-0d34-0410-b5e6-96231b3b80d8
			
			
This commit is contained in:
		| @@ -1699,14 +1699,6 @@ This should be optimized to a single compare.  Testcase derived from gcc. | |||||||
|  |  | ||||||
| //===---------------------------------------------------------------------===// | //===---------------------------------------------------------------------===// | ||||||
|  |  | ||||||
| Missed instcombine transformation: |  | ||||||
| void b(); |  | ||||||
| void a(int x) { if (((1<<x)&8)==0) b(); } |  | ||||||
|  |  | ||||||
| The shift should be optimized out.  Testcase derived from gcc. |  | ||||||
|  |  | ||||||
| //===---------------------------------------------------------------------===// |  | ||||||
|  |  | ||||||
| Missed instcombine or reassociate transformation: | Missed instcombine or reassociate transformation: | ||||||
| int a(int a, int b) { return (a==12)&(b>47)&(b<58); } | int a(int a, int b) { return (a==12)&(b>47)&(b<58); } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1744,14 +1744,84 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) { | |||||||
|     // simplify this comparison.  For example, (x&4) < 8  is always true. |     // simplify this comparison.  For example, (x&4) < 8  is always true. | ||||||
|     switch (I.getPredicate()) { |     switch (I.getPredicate()) { | ||||||
|     default: llvm_unreachable("Unknown icmp opcode!"); |     default: llvm_unreachable("Unknown icmp opcode!"); | ||||||
|     case ICmpInst::ICMP_EQ: |     case ICmpInst::ICMP_EQ: { | ||||||
|       if (Op0Max.ult(Op1Min) || Op0Min.ugt(Op1Max)) |       if (Op0Max.ult(Op1Min) || Op0Min.ugt(Op1Max)) | ||||||
|         return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getContext())); |         return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getContext())); | ||||||
|  |          | ||||||
|  |       // If all bits are known zero except for one, then we know at most one | ||||||
|  |       // bit is set.   If the comparison is against zero, then this is a check | ||||||
|  |       // to see if *that* bit is set. | ||||||
|  |       APInt Op0KnownZeroInverted = ~Op0KnownZero; | ||||||
|  |       if (~Op1KnownZero == 0 && Op0KnownZeroInverted.isPowerOf2()) { | ||||||
|  |         // If the LHS is an AND with the same constant, look through it. | ||||||
|  |         Value *LHS = 0; | ||||||
|  |         ConstantInt *LHSC = 0; | ||||||
|  |         if (!match(Op0, m_And(m_Value(LHS), m_ConstantInt(LHSC))) || | ||||||
|  |             LHSC->getValue() != Op0KnownZeroInverted) | ||||||
|  |           LHS = Op0; | ||||||
|  |          | ||||||
|  |         // If the LHS is 1 << x, and we know the result is a power of 2 like 8, | ||||||
|  |         // then turn "((1 << x)&8) == 0" into "x == 3". | ||||||
|  |         Value *X = 0; | ||||||
|  |         if (match(LHS, m_Shl(m_One(), m_Value(X)))) { | ||||||
|  |           unsigned CmpVal = Op0KnownZeroInverted.countTrailingZeros(); | ||||||
|  |           return new ICmpInst(ICmpInst::ICMP_EQ, X, | ||||||
|  |                               ConstantInt::get(X->getType(), CmpVal)); | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         // If the LHS is 8 >>u x, and we know the result is a power of 2 like 1, | ||||||
|  |         // then turn "((8 >>u x)&1) == 0" into "x == 3". | ||||||
|  |         ConstantInt *CI = 0; | ||||||
|  |         if (Op0KnownZeroInverted == 1 && | ||||||
|  |             match(LHS, m_LShr(m_ConstantInt(CI), m_Value(X))) && | ||||||
|  |             CI->getValue().isPowerOf2()) { | ||||||
|  |           unsigned CmpVal = CI->getValue().countTrailingZeros(); | ||||||
|  |           return new ICmpInst(ICmpInst::ICMP_EQ, X, | ||||||
|  |                               ConstantInt::get(X->getType(), CmpVal)); | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |          | ||||||
|       break; |       break; | ||||||
|     case ICmpInst::ICMP_NE: |     } | ||||||
|  |     case ICmpInst::ICMP_NE: { | ||||||
|       if (Op0Max.ult(Op1Min) || Op0Min.ugt(Op1Max)) |       if (Op0Max.ult(Op1Min) || Op0Min.ugt(Op1Max)) | ||||||
|         return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getContext())); |         return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getContext())); | ||||||
|  |        | ||||||
|  |       // If all bits are known zero except for one, then we know at most one | ||||||
|  |       // bit is set.   If the comparison is against zero, then this is a check | ||||||
|  |       // to see if *that* bit is set. | ||||||
|  |       APInt Op0KnownZeroInverted = ~Op0KnownZero; | ||||||
|  |       if (~Op1KnownZero == 0 && Op0KnownZeroInverted.isPowerOf2()) { | ||||||
|  |         // If the LHS is an AND with the same constant, look through it. | ||||||
|  |         Value *LHS = 0; | ||||||
|  |         ConstantInt *LHSC = 0; | ||||||
|  |         if (!match(Op0, m_And(m_Value(LHS), m_ConstantInt(LHSC))) || | ||||||
|  |             LHSC->getValue() != Op0KnownZeroInverted) | ||||||
|  |           LHS = Op0; | ||||||
|  |          | ||||||
|  |         // If the LHS is 1 << x, and we know the result is a power of 2 like 8, | ||||||
|  |         // then turn "((1 << x)&8) != 0" into "x != 3". | ||||||
|  |         Value *X = 0; | ||||||
|  |         if (match(LHS, m_Shl(m_One(), m_Value(X)))) { | ||||||
|  |           unsigned CmpVal = Op0KnownZeroInverted.countTrailingZeros(); | ||||||
|  |           return new ICmpInst(ICmpInst::ICMP_NE, X, | ||||||
|  |                               ConstantInt::get(X->getType(), CmpVal)); | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         // If the LHS is 8 >>u x, and we know the result is a power of 2 like 1, | ||||||
|  |         // then turn "((8 >>u x)&1) != 0" into "x != 3". | ||||||
|  |         ConstantInt *CI = 0; | ||||||
|  |         if (Op0KnownZeroInverted == 1 && | ||||||
|  |             match(LHS, m_LShr(m_ConstantInt(CI), m_Value(X))) && | ||||||
|  |             CI->getValue().isPowerOf2()) { | ||||||
|  |           unsigned CmpVal = CI->getValue().countTrailingZeros(); | ||||||
|  |           return new ICmpInst(ICmpInst::ICMP_NE, X, | ||||||
|  |                               ConstantInt::get(X->getType(), CmpVal)); | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |        | ||||||
|       break; |       break; | ||||||
|  |     } | ||||||
|     case ICmpInst::ICMP_ULT: |     case ICmpInst::ICMP_ULT: | ||||||
|       if (Op0Max.ult(Op1Min))          // A <u B -> true if max(A) < min(B) |       if (Op0Max.ult(Op1Min))          // A <u B -> true if max(A) < min(B) | ||||||
|         return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getContext())); |         return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getContext())); | ||||||
|   | |||||||
| @@ -154,3 +154,41 @@ entry: | |||||||
| ; CHECK: @test16 | ; CHECK: @test16 | ||||||
| ; CHECK: ret i1 undef | ; CHECK: ret i1 undef | ||||||
| } | } | ||||||
|  |  | ||||||
|  | define i1 @test17(i32 %x) nounwind { | ||||||
|  |   %shl = shl i32 1, %x | ||||||
|  |   %and = and i32 %shl, 8 | ||||||
|  |   %cmp = icmp eq i32 %and, 0 | ||||||
|  |   ret i1 %cmp | ||||||
|  | ; CHECK: @test17 | ||||||
|  | ; CHECK-NEXT: %cmp = icmp eq i32 %x, 3 | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | define i1 @test18(i32 %x) nounwind { | ||||||
|  |   %sh = lshr i32 8, %x | ||||||
|  |   %and = and i32 %sh, 1 | ||||||
|  |   %cmp = icmp eq i32 %and, 0 | ||||||
|  |   ret i1 %cmp | ||||||
|  | ; CHECK: @test18 | ||||||
|  | ; CHECK-NEXT: %cmp = icmp eq i32 %x, 3 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | define i1 @test19(i32 %x) nounwind { | ||||||
|  |   %shl = shl i32 1, %x | ||||||
|  |   %and = and i32 %shl, 8 | ||||||
|  |   %cmp = icmp eq i32 %and, 8 | ||||||
|  |   ret i1 %cmp | ||||||
|  | ; CHECK: @test19 | ||||||
|  | ; CHECK-NEXT: %cmp = icmp ne i32 %x, 3 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | define i1 @test20(i32 %x) nounwind { | ||||||
|  |   %shl = shl i32 1, %x | ||||||
|  |   %and = and i32 %shl, 8 | ||||||
|  |   %cmp = icmp ne i32 %and, 0 | ||||||
|  |   ret i1 %cmp | ||||||
|  | ; CHECK: @test20 | ||||||
|  | ; CHECK-NEXT: %cmp = icmp ne i32 %x, 3 | ||||||
|  | } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user