mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-10-30 16:17:05 +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: | ||||
| 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. | ||||
|     switch (I.getPredicate()) { | ||||
|     default: llvm_unreachable("Unknown icmp opcode!"); | ||||
|     case ICmpInst::ICMP_EQ: | ||||
|     case ICmpInst::ICMP_EQ: { | ||||
|       if (Op0Max.ult(Op1Min) || Op0Min.ugt(Op1Max)) | ||||
|         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; | ||||
|     case ICmpInst::ICMP_NE: | ||||
|     } | ||||
|     case ICmpInst::ICMP_NE: { | ||||
|       if (Op0Max.ult(Op1Min) || Op0Min.ugt(Op1Max)) | ||||
|         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; | ||||
|     } | ||||
|     case ICmpInst::ICMP_ULT: | ||||
|       if (Op0Max.ult(Op1Min))          // A <u B -> true if max(A) < min(B) | ||||
|         return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getContext())); | ||||
|   | ||||
| @@ -154,3 +154,41 @@ entry: | ||||
| ; CHECK: @test16 | ||||
| ; 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