mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-10-31 08:16:47 +00:00 
			
		
		
		
	Carve out a place in instcombine to put transformations which work knowing that their
result is non-zero. Implement an example optimization (PR9814), which allows us to transform: A / ((1 << B) >>u 2) into: A >>u (B-2) which we compile into: _divu3: ## @divu3 leal -2(%rsi), %ecx shrl %cl, %edi movl %edi, %eax ret instead of: _divu3: ## @divu3 movb %sil, %cl movl $1, %esi shll %cl, %esi shrl $2, %esi movl %edi, %eax xorl %edx, %edx divl %esi, %eax ret git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@131860 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
		| @@ -19,6 +19,31 @@ | |||||||
| using namespace llvm; | using namespace llvm; | ||||||
| using namespace PatternMatch; | using namespace PatternMatch; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /// simplifyValueKnownNonZero - The specific integer value is used in a context | ||||||
|  | /// where it is known to be non-zero.  If this allows us to simplify the | ||||||
|  | /// computation, do so and return the new operand, otherwise return null. | ||||||
|  | static Value *simplifyValueKnownNonZero(Value *V, InstCombiner &IC) { | ||||||
|  |   // If V has multiple uses, then we would have to do more analysis to determine | ||||||
|  |   // if this is safe.  For example, the use could be in dynamically unreached | ||||||
|  |   // code. | ||||||
|  |   if (!V->hasOneUse()) return 0; | ||||||
|  |    | ||||||
|  |   // ((1 << A) >>u B) --> (1 << (A-B)) | ||||||
|  |   // Because V cannot be zero, we know that B is less than A. | ||||||
|  |   Value *A = 0, *B = 0; ConstantInt *One = 0; | ||||||
|  |   if (match(V, m_LShr(m_OneUse(m_Shl(m_ConstantInt(One), m_Value(A))), | ||||||
|  |                       m_Value(B))) && | ||||||
|  |       // The "1" can be any value known to be a power of 2. | ||||||
|  |       One->getValue().isPowerOf2()) { | ||||||
|  |     A = IC.Builder->CreateSub(A, B, "tmp"); | ||||||
|  |     return IC.Builder->CreateShl(One, A); | ||||||
|  |   } | ||||||
|  |    | ||||||
|  |   return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
| /// MultiplyOverflows - True if the multiply can not be expressed in an int | /// MultiplyOverflows - True if the multiply can not be expressed in an int | ||||||
| /// this size. | /// this size. | ||||||
| static bool MultiplyOverflows(ConstantInt *C1, ConstantInt *C2, bool sign) { | static bool MultiplyOverflows(ConstantInt *C1, ConstantInt *C2, bool sign) { | ||||||
| @@ -293,6 +318,12 @@ bool InstCombiner::SimplifyDivRemOfSelect(BinaryOperator &I) { | |||||||
| Instruction *InstCombiner::commonIDivTransforms(BinaryOperator &I) { | Instruction *InstCombiner::commonIDivTransforms(BinaryOperator &I) { | ||||||
|   Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); |   Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); | ||||||
|  |  | ||||||
|  |   // The RHS is known non-zero. | ||||||
|  |   if (Value *V = simplifyValueKnownNonZero(I.getOperand(1), *this)) { | ||||||
|  |     I.setOperand(1, V); | ||||||
|  |     return &I; | ||||||
|  |   } | ||||||
|  |    | ||||||
|   // Handle cases involving: [su]div X, (select Cond, Y, Z) |   // Handle cases involving: [su]div X, (select Cond, Y, Z) | ||||||
|   // This does not apply for fdiv. |   // This does not apply for fdiv. | ||||||
|   if (isa<SelectInst>(Op1) && SimplifyDivRemOfSelect(I)) |   if (isa<SelectInst>(Op1) && SimplifyDivRemOfSelect(I)) | ||||||
| @@ -499,6 +530,12 @@ Instruction *InstCombiner::visitFDiv(BinaryOperator &I) { | |||||||
| Instruction *InstCombiner::commonIRemTransforms(BinaryOperator &I) { | Instruction *InstCombiner::commonIRemTransforms(BinaryOperator &I) { | ||||||
|   Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); |   Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); | ||||||
|  |  | ||||||
|  |   // The RHS is known non-zero. | ||||||
|  |   if (Value *V = simplifyValueKnownNonZero(I.getOperand(1), *this)) { | ||||||
|  |     I.setOperand(1, V); | ||||||
|  |     return &I; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   // Handle cases involving: rem X, (select Cond, Y, Z) |   // Handle cases involving: rem X, (select Cond, Y, Z) | ||||||
|   if (isa<SelectInst>(Op1) && SimplifyDivRemOfSelect(I)) |   if (isa<SelectInst>(Op1) && SimplifyDivRemOfSelect(I)) | ||||||
|     return &I; |     return &I; | ||||||
|   | |||||||
| @@ -118,3 +118,17 @@ define i32 @test14(i8 %x) nounwind { | |||||||
| ; CHECK: @test14 | ; CHECK: @test14 | ||||||
| ; CHECK-NEXT: ret i32 0 | ; CHECK-NEXT: ret i32 0 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | ; PR9814 | ||||||
|  | define i32 @test15(i32 %a, i32 %b) nounwind { | ||||||
|  |   %shl = shl i32 1, %b | ||||||
|  |   %div = lshr i32 %shl, 2 | ||||||
|  |   %div2 = udiv i32 %a, %div | ||||||
|  |   ret i32 %div2 | ||||||
|  | ; CHECK: @test15 | ||||||
|  | ; CHECK-NEXT: add i32 %b, -2 | ||||||
|  | ; CHECK-NEXT: lshr i32 %a,  | ||||||
|  | ; CHECK-NEXT: ret i32 | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user