Fix PR13991: legalizing an overflowing multiplication operation is harder than
the add/sub case since in the case of multiplication you also have to check that the operation in the larger type did not overflow. llvm-svn: 165017
This commit is contained in:
		
							parent
							
								
									a99c35702d
								
							
						
					
					
						commit
						f97cb15aee
					
				| 
						 | 
					@ -644,8 +644,9 @@ SDValue DAGTypeLegalizer::PromoteIntRes_XMULO(SDNode *N, unsigned ResNo) {
 | 
				
			||||||
  EVT SmallVT = LHS.getValueType();
 | 
					  EVT SmallVT = LHS.getValueType();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // To determine if the result overflowed in a larger type, we extend the
 | 
					  // To determine if the result overflowed in a larger type, we extend the
 | 
				
			||||||
  // input to the larger type, do the multiply, then check the high bits of
 | 
					  // input to the larger type, do the multiply (checking if it overflows),
 | 
				
			||||||
  // the result to see if the overflow happened.
 | 
					  // then also check the high bits of the result to see if overflow happened
 | 
				
			||||||
 | 
					  // there.
 | 
				
			||||||
  if (N->getOpcode() == ISD::SMULO) {
 | 
					  if (N->getOpcode() == ISD::SMULO) {
 | 
				
			||||||
    LHS = SExtPromotedInteger(LHS);
 | 
					    LHS = SExtPromotedInteger(LHS);
 | 
				
			||||||
    RHS = SExtPromotedInteger(RHS);
 | 
					    RHS = SExtPromotedInteger(RHS);
 | 
				
			||||||
| 
						 | 
					@ -653,24 +654,31 @@ SDValue DAGTypeLegalizer::PromoteIntRes_XMULO(SDNode *N, unsigned ResNo) {
 | 
				
			||||||
    LHS = ZExtPromotedInteger(LHS);
 | 
					    LHS = ZExtPromotedInteger(LHS);
 | 
				
			||||||
    RHS = ZExtPromotedInteger(RHS);
 | 
					    RHS = ZExtPromotedInteger(RHS);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  SDValue Mul = DAG.getNode(ISD::MUL, DL, LHS.getValueType(), LHS, RHS);
 | 
					  SDVTList VTs = DAG.getVTList(LHS.getValueType(), N->getValueType(1));
 | 
				
			||||||
 | 
					  SDValue Mul = DAG.getNode(N->getOpcode(), DL, VTs, LHS, RHS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Overflow occurred iff the high part of the result does not
 | 
					  // Overflow occurred if it occurred in the larger type, or if the high part
 | 
				
			||||||
  // zero/sign-extend the low part.
 | 
					  // of the result does not zero/sign-extend the low part.  Check this second
 | 
				
			||||||
 | 
					  // possibility first.
 | 
				
			||||||
  SDValue Overflow;
 | 
					  SDValue Overflow;
 | 
				
			||||||
  if (N->getOpcode() == ISD::UMULO) {
 | 
					  if (N->getOpcode() == ISD::UMULO) {
 | 
				
			||||||
    // Unsigned overflow occurred iff the high part is non-zero.
 | 
					    // Unsigned overflow occurred if the high part is non-zero.
 | 
				
			||||||
    SDValue Hi = DAG.getNode(ISD::SRL, DL, Mul.getValueType(), Mul,
 | 
					    SDValue Hi = DAG.getNode(ISD::SRL, DL, Mul.getValueType(), Mul,
 | 
				
			||||||
                             DAG.getIntPtrConstant(SmallVT.getSizeInBits()));
 | 
					                             DAG.getIntPtrConstant(SmallVT.getSizeInBits()));
 | 
				
			||||||
    Overflow = DAG.getSetCC(DL, N->getValueType(1), Hi,
 | 
					    Overflow = DAG.getSetCC(DL, N->getValueType(1), Hi,
 | 
				
			||||||
                            DAG.getConstant(0, Hi.getValueType()), ISD::SETNE);
 | 
					                            DAG.getConstant(0, Hi.getValueType()), ISD::SETNE);
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    // Signed overflow occurred iff the high part does not sign extend the low.
 | 
					    // Signed overflow occurred if the high part does not sign extend the low.
 | 
				
			||||||
    SDValue SExt = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, Mul.getValueType(),
 | 
					    SDValue SExt = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, Mul.getValueType(),
 | 
				
			||||||
                               Mul, DAG.getValueType(SmallVT));
 | 
					                               Mul, DAG.getValueType(SmallVT));
 | 
				
			||||||
    Overflow = DAG.getSetCC(DL, N->getValueType(1), SExt, Mul, ISD::SETNE);
 | 
					    Overflow = DAG.getSetCC(DL, N->getValueType(1), SExt, Mul, ISD::SETNE);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // The only other way for overflow to occur is if the multiplication in the
 | 
				
			||||||
 | 
					  // larger type itself overflowed.
 | 
				
			||||||
 | 
					  Overflow = DAG.getNode(ISD::OR, DL, N->getValueType(1), Overflow,
 | 
				
			||||||
 | 
					                         SDValue(Mul.getNode(), 1));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Use the calculated overflow everywhere.
 | 
					  // Use the calculated overflow everywhere.
 | 
				
			||||||
  ReplaceValueWith(SDValue(N, 1), Overflow);
 | 
					  ReplaceValueWith(SDValue(N, 1), Overflow);
 | 
				
			||||||
  return Mul;
 | 
					  return Mul;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -67,3 +67,17 @@ entry:
 | 
				
			||||||
; CHECK: mull
 | 
					; CHECK: mull
 | 
				
			||||||
; CHECK-NEXT: ret
 | 
					; CHECK-NEXT: ret
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					declare { i63, i1 } @llvm.smul.with.overflow.i63(i63, i63) nounwind readnone
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					define i1 @test5() nounwind {
 | 
				
			||||||
 | 
					entry:
 | 
				
			||||||
 | 
					  %res = call { i63, i1 } @llvm.smul.with.overflow.i63(i63 4, i63 4611686018427387903)
 | 
				
			||||||
 | 
					  %sum = extractvalue { i63, i1 } %res, 0
 | 
				
			||||||
 | 
					  %overflow = extractvalue { i63, i1 } %res, 1
 | 
				
			||||||
 | 
					  ret i1 %overflow
 | 
				
			||||||
 | 
					; Was returning false, should return true (not constant folded yet though).
 | 
				
			||||||
 | 
					; PR13991
 | 
				
			||||||
 | 
					; CHECK: test5:
 | 
				
			||||||
 | 
					; CHECK-NOT: xorb
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue