[InstCombine] fold min/max intrinsic with negated operand to abs
The smax case shows up in https://llvm.org/PR49885 . The others seem unlikely, but we might as well try for uniformity (although that could mean an extra instruction to create "nabs"). smax -- https://alive2.llvm.org/ce/z/8yYaGy smin -- https://alive2.llvm.org/ce/z/0_7zc_ umax -- https://alive2.llvm.org/ce/z/EcsZWs umin -- https://alive2.llvm.org/ce/z/Xw6WvB
This commit is contained in:
		
							parent
							
								
									c52dbdbc33
								
							
						
					
					
						commit
						5094e1279e
					
				| 
						 | 
					@ -911,6 +911,22 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // smax(X, -X) --> abs(X)
 | 
				
			||||||
 | 
					    // smin(X, -X) --> -abs(X)
 | 
				
			||||||
 | 
					    // umax(X, -X) --> -abs(X)
 | 
				
			||||||
 | 
					    // umin(X, -X) --> abs(X)
 | 
				
			||||||
 | 
					    if (isKnownNegation(I0, I1)) {
 | 
				
			||||||
 | 
					      // This is some variant of abs(). See if we can propagate 'nsw' to the abs
 | 
				
			||||||
 | 
					      // operation and potentially its negation.
 | 
				
			||||||
 | 
					      bool IntMinIsPoison = isKnownNegation(I0, I1, /* NeedNSW */ true);
 | 
				
			||||||
 | 
					      Value *Abs = Builder.CreateBinaryIntrinsic(
 | 
				
			||||||
 | 
					          Intrinsic::abs, I0,
 | 
				
			||||||
 | 
					          ConstantInt::getBool(II->getContext(), IntMinIsPoison));
 | 
				
			||||||
 | 
					      if (IID == Intrinsic::smin || IID == Intrinsic::umax)
 | 
				
			||||||
 | 
					        Abs = Builder.CreateNeg(Abs, "nabs", /* NUW */ false, IntMinIsPoison);
 | 
				
			||||||
 | 
					      return replaceInstUsesWith(CI, Abs);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    break;
 | 
					    break;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  case Intrinsic::bswap: {
 | 
					  case Intrinsic::bswap: {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -611,9 +611,8 @@ define i8 @not_umin_of_not_constant_op(i8 %x) {
 | 
				
			||||||
define i8 @smax_negation(i8 %x, i8 %y) {
 | 
					define i8 @smax_negation(i8 %x, i8 %y) {
 | 
				
			||||||
; CHECK-LABEL: @smax_negation(
 | 
					; CHECK-LABEL: @smax_negation(
 | 
				
			||||||
; CHECK-NEXT:    [[S1:%.*]] = sub i8 [[X:%.*]], [[Y:%.*]]
 | 
					; CHECK-NEXT:    [[S1:%.*]] = sub i8 [[X:%.*]], [[Y:%.*]]
 | 
				
			||||||
; CHECK-NEXT:    [[S2:%.*]] = sub i8 [[Y]], [[X]]
 | 
					; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[S1]], i1 false)
 | 
				
			||||||
; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.smax.i8(i8 [[S1]], i8 [[S2]])
 | 
					; CHECK-NEXT:    ret i8 [[TMP1]]
 | 
				
			||||||
; CHECK-NEXT:    ret i8 [[R]]
 | 
					 | 
				
			||||||
;
 | 
					;
 | 
				
			||||||
  %s1 = sub i8 %x, %y
 | 
					  %s1 = sub i8 %x, %y
 | 
				
			||||||
  %s2 = sub i8 %y, %x
 | 
					  %s2 = sub i8 %y, %x
 | 
				
			||||||
| 
						 | 
					@ -624,9 +623,8 @@ define i8 @smax_negation(i8 %x, i8 %y) {
 | 
				
			||||||
define i8 @smax_negation_nsw(i8 %x, i8 %y) {
 | 
					define i8 @smax_negation_nsw(i8 %x, i8 %y) {
 | 
				
			||||||
; CHECK-LABEL: @smax_negation_nsw(
 | 
					; CHECK-LABEL: @smax_negation_nsw(
 | 
				
			||||||
; CHECK-NEXT:    [[S1:%.*]] = sub nsw i8 [[X:%.*]], [[Y:%.*]]
 | 
					; CHECK-NEXT:    [[S1:%.*]] = sub nsw i8 [[X:%.*]], [[Y:%.*]]
 | 
				
			||||||
; CHECK-NEXT:    [[S2:%.*]] = sub nsw i8 [[Y]], [[X]]
 | 
					; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[S1]], i1 true)
 | 
				
			||||||
; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.smax.i8(i8 [[S1]], i8 [[S2]])
 | 
					; CHECK-NEXT:    ret i8 [[TMP1]]
 | 
				
			||||||
; CHECK-NEXT:    ret i8 [[R]]
 | 
					 | 
				
			||||||
;
 | 
					;
 | 
				
			||||||
  %s1 = sub nsw i8 %x, %y
 | 
					  %s1 = sub nsw i8 %x, %y
 | 
				
			||||||
  %s2 = sub nsw i8 %y, %x
 | 
					  %s2 = sub nsw i8 %y, %x
 | 
				
			||||||
| 
						 | 
					@ -637,9 +635,8 @@ define i8 @smax_negation_nsw(i8 %x, i8 %y) {
 | 
				
			||||||
define i8 @smax_negation_not_nsw(i8 %x, i8 %y) {
 | 
					define i8 @smax_negation_not_nsw(i8 %x, i8 %y) {
 | 
				
			||||||
; CHECK-LABEL: @smax_negation_not_nsw(
 | 
					; CHECK-LABEL: @smax_negation_not_nsw(
 | 
				
			||||||
; CHECK-NEXT:    [[S1:%.*]] = sub nsw i8 [[X:%.*]], [[Y:%.*]]
 | 
					; CHECK-NEXT:    [[S1:%.*]] = sub nsw i8 [[X:%.*]], [[Y:%.*]]
 | 
				
			||||||
; CHECK-NEXT:    [[S2:%.*]] = sub nuw i8 [[Y]], [[X]]
 | 
					; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[S1]], i1 false)
 | 
				
			||||||
; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.smax.i8(i8 [[S1]], i8 [[S2]])
 | 
					; CHECK-NEXT:    ret i8 [[TMP1]]
 | 
				
			||||||
; CHECK-NEXT:    ret i8 [[R]]
 | 
					 | 
				
			||||||
;
 | 
					;
 | 
				
			||||||
  %s1 = sub nsw i8 %x, %y
 | 
					  %s1 = sub nsw i8 %x, %y
 | 
				
			||||||
  %s2 = sub nuw i8 %y, %x
 | 
					  %s2 = sub nuw i8 %y, %x
 | 
				
			||||||
| 
						 | 
					@ -649,9 +646,8 @@ define i8 @smax_negation_not_nsw(i8 %x, i8 %y) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
define <3 x i8> @smax_negation_vec(<3 x i8> %x) {
 | 
					define <3 x i8> @smax_negation_vec(<3 x i8> %x) {
 | 
				
			||||||
; CHECK-LABEL: @smax_negation_vec(
 | 
					; CHECK-LABEL: @smax_negation_vec(
 | 
				
			||||||
; CHECK-NEXT:    [[S:%.*]] = sub <3 x i8> <i8 0, i8 undef, i8 0>, [[X:%.*]]
 | 
					; CHECK-NEXT:    [[TMP1:%.*]] = call <3 x i8> @llvm.abs.v3i8(<3 x i8> [[X:%.*]], i1 false)
 | 
				
			||||||
; CHECK-NEXT:    [[R:%.*]] = call <3 x i8> @llvm.smax.v3i8(<3 x i8> [[X]], <3 x i8> [[S]])
 | 
					; CHECK-NEXT:    ret <3 x i8> [[TMP1]]
 | 
				
			||||||
; CHECK-NEXT:    ret <3 x i8> [[R]]
 | 
					 | 
				
			||||||
;
 | 
					;
 | 
				
			||||||
  %s = sub <3 x i8> <i8 0, i8 undef, i8 0>, %x
 | 
					  %s = sub <3 x i8> <i8 0, i8 undef, i8 0>, %x
 | 
				
			||||||
  %r = call <3 x i8> @llvm.smax.v3i8(<3 x i8> %x, <3 x i8> %s)
 | 
					  %r = call <3 x i8> @llvm.smax.v3i8(<3 x i8> %x, <3 x i8> %s)
 | 
				
			||||||
| 
						 | 
					@ -661,9 +657,9 @@ define <3 x i8> @smax_negation_vec(<3 x i8> %x) {
 | 
				
			||||||
define i8 @smin_negation(i8 %x, i8 %y) {
 | 
					define i8 @smin_negation(i8 %x, i8 %y) {
 | 
				
			||||||
; CHECK-LABEL: @smin_negation(
 | 
					; CHECK-LABEL: @smin_negation(
 | 
				
			||||||
; CHECK-NEXT:    [[S1:%.*]] = sub i8 [[X:%.*]], [[Y:%.*]]
 | 
					; CHECK-NEXT:    [[S1:%.*]] = sub i8 [[X:%.*]], [[Y:%.*]]
 | 
				
			||||||
; CHECK-NEXT:    [[S2:%.*]] = sub i8 [[Y]], [[X]]
 | 
					; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[S1]], i1 false)
 | 
				
			||||||
; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.smin.i8(i8 [[S1]], i8 [[S2]])
 | 
					; CHECK-NEXT:    [[NABS:%.*]] = sub i8 0, [[TMP1]]
 | 
				
			||||||
; CHECK-NEXT:    ret i8 [[R]]
 | 
					; CHECK-NEXT:    ret i8 [[NABS]]
 | 
				
			||||||
;
 | 
					;
 | 
				
			||||||
  %s1 = sub i8 %x, %y
 | 
					  %s1 = sub i8 %x, %y
 | 
				
			||||||
  %s2 = sub i8 %y, %x
 | 
					  %s2 = sub i8 %y, %x
 | 
				
			||||||
| 
						 | 
					@ -674,9 +670,9 @@ define i8 @smin_negation(i8 %x, i8 %y) {
 | 
				
			||||||
define i8 @umax_negation(i8 %x, i8 %y) {
 | 
					define i8 @umax_negation(i8 %x, i8 %y) {
 | 
				
			||||||
; CHECK-LABEL: @umax_negation(
 | 
					; CHECK-LABEL: @umax_negation(
 | 
				
			||||||
; CHECK-NEXT:    [[S1:%.*]] = sub nsw i8 [[X:%.*]], [[Y:%.*]]
 | 
					; CHECK-NEXT:    [[S1:%.*]] = sub nsw i8 [[X:%.*]], [[Y:%.*]]
 | 
				
			||||||
; CHECK-NEXT:    [[S2:%.*]] = sub nsw i8 [[Y]], [[X]]
 | 
					; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[S1]], i1 true)
 | 
				
			||||||
; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.umax.i8(i8 [[S1]], i8 [[S2]])
 | 
					; CHECK-NEXT:    [[NABS:%.*]] = sub nsw i8 0, [[TMP1]]
 | 
				
			||||||
; CHECK-NEXT:    ret i8 [[R]]
 | 
					; CHECK-NEXT:    ret i8 [[NABS]]
 | 
				
			||||||
;
 | 
					;
 | 
				
			||||||
  %s1 = sub nsw i8 %x, %y
 | 
					  %s1 = sub nsw i8 %x, %y
 | 
				
			||||||
  %s2 = sub nsw i8 %y, %x
 | 
					  %s2 = sub nsw i8 %y, %x
 | 
				
			||||||
| 
						 | 
					@ -686,9 +682,8 @@ define i8 @umax_negation(i8 %x, i8 %y) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
define i8 @umin_negation(i8 %x) {
 | 
					define i8 @umin_negation(i8 %x) {
 | 
				
			||||||
; CHECK-LABEL: @umin_negation(
 | 
					; CHECK-LABEL: @umin_negation(
 | 
				
			||||||
; CHECK-NEXT:    [[S:%.*]] = sub nsw i8 0, [[X:%.*]]
 | 
					; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 true)
 | 
				
			||||||
; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.umin.i8(i8 [[S]], i8 [[X]])
 | 
					; CHECK-NEXT:    ret i8 [[TMP1]]
 | 
				
			||||||
; CHECK-NEXT:    ret i8 [[R]]
 | 
					 | 
				
			||||||
;
 | 
					;
 | 
				
			||||||
  %s = sub nsw i8 0, %x
 | 
					  %s = sub nsw i8 0, %x
 | 
				
			||||||
  %r = call i8 @llvm.umin.i8(i8 %s, i8 %x)
 | 
					  %r = call i8 @llvm.umin.i8(i8 %s, i8 %x)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue