forked from OSchip/llvm-project
				
			getSExtValue() doesn't work for ConstantInts with bitwidth > 64 bits. Use all
APInt calls instead. This fixes PR3144. llvm-svn: 60288
This commit is contained in:
		
							parent
							
								
									09bc610945
								
							
						
					
					
						commit
						2d2e7861b5
					
				| 
						 | 
				
			
			@ -2957,21 +2957,21 @@ Instruction *InstCombiner::visitSDiv(BinaryOperator &I) {
 | 
			
		|||
      return BinaryOperator::CreateNeg(Op0);
 | 
			
		||||
 | 
			
		||||
    ConstantInt *RHSNeg = cast<ConstantInt>(ConstantExpr::getNeg(RHS));
 | 
			
		||||
    APInt RHSNegAPI(RHSNeg->getBitWidth(), RHSNeg->getSExtValue(), true);
 | 
			
		||||
    APInt RHSNegAPI(RHSNeg->getValue());
 | 
			
		||||
 | 
			
		||||
    APInt NegOne = -APInt(RHSNeg->getBitWidth(), 1, true);
 | 
			
		||||
    APInt TwoToExp(RHSNeg->getBitWidth(), 1 << (RHSNeg->getBitWidth() - 1));
 | 
			
		||||
 | 
			
		||||
    // -X/C -> X/-C, if and only if negation doesn't overflow.
 | 
			
		||||
    if ((RHS->getSExtValue() < 0 && RHSNegAPI.slt(TwoToExp - 1)) ||
 | 
			
		||||
        (RHS->getSExtValue() > 0 && RHSNegAPI.sgt(TwoToExp * NegOne))) {
 | 
			
		||||
    if ((RHS->getValue().isNegative() && RHSNegAPI.slt(TwoToExp - 1)) ||
 | 
			
		||||
        (RHS->getValue().isNonNegative() && RHSNegAPI.sgt(TwoToExp * NegOne))) {
 | 
			
		||||
      if (Value *LHSNeg = dyn_castNegVal(Op0)) {
 | 
			
		||||
        if (ConstantInt *CI = dyn_cast<ConstantInt>(LHSNeg)) {
 | 
			
		||||
          ConstantInt *CINeg = cast<ConstantInt>(ConstantExpr::getNeg(CI));
 | 
			
		||||
          APInt CINegAPI(CINeg->getBitWidth(), CINeg->getSExtValue(), true);
 | 
			
		||||
 | 
			
		||||
          if ((CI->getSExtValue() < 0 && CINegAPI.slt(TwoToExp - 1)) ||
 | 
			
		||||
              (CI->getSExtValue() > 0 && CINegAPI.sgt(TwoToExp * NegOne)))
 | 
			
		||||
          if ((CI->getValue().isNegative() && CINegAPI.slt(TwoToExp - 1)) ||
 | 
			
		||||
              (CI->getValue().isNonNegative() && CINegAPI.sgt(TwoToExp*NegOne)))
 | 
			
		||||
            return BinaryOperator::CreateSDiv(LHSNeg,
 | 
			
		||||
                                              ConstantExpr::getNeg(RHS));
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,28 @@
 | 
			
		|||
; RUN: llvm-as < %s | opt -instcombine -disable-output
 | 
			
		||||
; PR3144
 | 
			
		||||
 | 
			
		||||
define fastcc i32 @func(i32 %length) nounwind {
 | 
			
		||||
entry:
 | 
			
		||||
	%0 = icmp ne i32 %length, -1		; <i1> [#uses=1]
 | 
			
		||||
	%iftmp.13.0 = select i1 %0, i128 0, i128 200000000		; <i128> [#uses=2]
 | 
			
		||||
	%1 = sdiv i128 %iftmp.13.0, 10		; <i128> [#uses=1]
 | 
			
		||||
	br label %bb5
 | 
			
		||||
 | 
			
		||||
bb5:		; preds = %bb8, %entry
 | 
			
		||||
	%v.0 = phi i128 [ 0, %entry ], [ %6, %bb8 ]		; <i128> [#uses=2]
 | 
			
		||||
	%2 = icmp sgt i128 %v.0, %1		; <i1> [#uses=1]
 | 
			
		||||
	br i1 %2, label %overflow, label %bb7
 | 
			
		||||
 | 
			
		||||
bb7:		; preds = %bb5
 | 
			
		||||
	%3 = mul i128 %v.0, 10		; <i128> [#uses=2]
 | 
			
		||||
	%4 = sub i128 %iftmp.13.0, 0		; <i128> [#uses=1]
 | 
			
		||||
	%5 = icmp slt i128 %4, %3		; <i1> [#uses=1]
 | 
			
		||||
	br i1 %5, label %overflow, label %bb8
 | 
			
		||||
 | 
			
		||||
bb8:		; preds = %bb7
 | 
			
		||||
	%6 = add i128 0, %3		; <i128> [#uses=1]
 | 
			
		||||
	br label %bb5
 | 
			
		||||
 | 
			
		||||
overflow:		; preds = %bb7, %bb5
 | 
			
		||||
	ret i32 1
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue