1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4; ((ashr X, 31) | 1 ) * X --> abs(X) 5; X * ((ashr X, 31) | 1 ) --> abs(X) 6 7define i32 @ashr_or_mul_to_abs(i32 %X) { 8; CHECK-LABEL: @ashr_or_mul_to_abs( 9; CHECK-NEXT: [[I2:%.*]] = call i32 @llvm.abs.i32(i32 [[X:%.*]], i1 true) 10; CHECK-NEXT: ret i32 [[I2]] 11; 12 %i = ashr i32 %X, 31 13 %i1 = or i32 %i, 1 14 %i2 = mul nsw i32 %i1, %X 15 ret i32 %i2 16} 17 18define i32 @ashr_or_mul_to_abs2(i32 %X) { 19; CHECK-LABEL: @ashr_or_mul_to_abs2( 20; CHECK-NEXT: [[I2:%.*]] = call i32 @llvm.abs.i32(i32 [[X:%.*]], i1 false) 21; CHECK-NEXT: ret i32 [[I2]] 22; 23 %i = ashr i32 %X, 31 24 %i1 = or i32 %i, 1 25 %i2 = mul i32 %i1, %X 26 ret i32 %i2 27} 28 29define i32 @ashr_or_mul_to_abs3(i32 %PX) { 30; CHECK-LABEL: @ashr_or_mul_to_abs3( 31; CHECK-NEXT: [[X:%.*]] = sdiv i32 42, [[PX:%.*]] 32; CHECK-NEXT: [[I2:%.*]] = call i32 @llvm.abs.i32(i32 [[X]], i1 false) 33; CHECK-NEXT: ret i32 [[I2]] 34; 35 %X = sdiv i32 42, %PX ; thwart complexity-based canonicalization 36 %i = ashr i32 %X, 31 37 %i1 = or i32 %i, 1 38 %i2 = mul i32 %X, %i1 39 ret i32 %i2 40} 41 42 43define <4 x i32> @ashr_or_mul_to_abs_vec(<4 x i32> %X) { 44; CHECK-LABEL: @ashr_or_mul_to_abs_vec( 45; CHECK-NEXT: [[I2:%.*]] = call <4 x i32> @llvm.abs.v4i32(<4 x i32> [[X:%.*]], i1 false) 46; CHECK-NEXT: ret <4 x i32> [[I2]] 47; 48 %i = ashr <4 x i32> %X, <i32 31, i32 31, i32 31, i32 31> 49 %i1 = or <4 x i32> %i, <i32 1, i32 1, i32 1, i32 1> 50 %i2 = mul <4 x i32> %i1, %X 51 ret <4 x i32> %i2 52} 53 54define <4 x i32> @ashr_or_mul_to_abs_vec2(<4 x i32> %X) { 55; CHECK-LABEL: @ashr_or_mul_to_abs_vec2( 56; CHECK-NEXT: [[I2:%.*]] = call <4 x i32> @llvm.abs.v4i32(<4 x i32> [[X:%.*]], i1 true) 57; CHECK-NEXT: ret <4 x i32> [[I2]] 58; 59 %i = ashr <4 x i32> %X, <i32 31, i32 31, i32 31, i32 31> 60 %i1 = or <4 x i32> %i, <i32 1, i32 1, i32 1, i32 1> 61 %i2 = mul nsw <4 x i32> %i1, %X 62 ret <4 x i32> %i2 63} 64 65define <4 x i32> @ashr_or_mul_to_abs_vec3_poison(<4 x i32> %X) { 66; CHECK-LABEL: @ashr_or_mul_to_abs_vec3_poison( 67; CHECK-NEXT: [[I2:%.*]] = call <4 x i32> @llvm.abs.v4i32(<4 x i32> [[X:%.*]], i1 false) 68; CHECK-NEXT: ret <4 x i32> [[I2]] 69; 70 %i = ashr <4 x i32> %X, <i32 31, i32 poison, i32 31, i32 31> 71 %i1 = or <4 x i32> %i, <i32 1, i32 1, i32 1, i32 poison> 72 %i2 = mul <4 x i32> %i1, %X 73 ret <4 x i32> %i2 74} 75 76; Negative tests 77 78define i32 @ashr_or_mul_to_abs_neg(i32 %X) { 79; CHECK-LABEL: @ashr_or_mul_to_abs_neg( 80; CHECK-NEXT: [[I:%.*]] = ashr i32 [[X:%.*]], 30 81; CHECK-NEXT: [[I1:%.*]] = or i32 [[I]], 1 82; CHECK-NEXT: [[I2:%.*]] = mul nsw i32 [[I1]], [[X]] 83; CHECK-NEXT: ret i32 [[I2]] 84; 85 %i = ashr i32 %X, 30 86 %i1 = or i32 %i, 1 87 %i2 = mul nsw i32 %i1, %X 88 ret i32 %i2 89} 90 91define i32 @ashr_or_mul_to_abs_neg2(i32 %X) { 92; CHECK-LABEL: @ashr_or_mul_to_abs_neg2( 93; CHECK-NEXT: [[I:%.*]] = ashr i32 [[X:%.*]], 31 94; CHECK-NEXT: [[I1:%.*]] = or i32 [[I]], 2 95; CHECK-NEXT: [[I2:%.*]] = mul nsw i32 [[I1]], [[X]] 96; CHECK-NEXT: ret i32 [[I2]] 97; 98 %i = ashr i32 %X, 31 99 %i1 = or i32 %i, 2 100 %i2 = mul nsw i32 %i1, %X 101 ret i32 %i2 102} 103 104define i32 @ashr_or_mul_to_abs_neg3(i32 %X, i32 %Y) { 105; CHECK-LABEL: @ashr_or_mul_to_abs_neg3( 106; CHECK-NEXT: [[I:%.*]] = ashr i32 [[X:%.*]], 31 107; CHECK-NEXT: [[I1:%.*]] = or i32 [[I]], 1 108; CHECK-NEXT: [[I2:%.*]] = mul nsw i32 [[I1]], [[Y:%.*]] 109; CHECK-NEXT: ret i32 [[I2]] 110; 111 %i = ashr i32 %X, 31 112 %i1 = or i32 %i, 1 113 %i2 = mul nsw i32 %i1, %Y 114 ret i32 %i2 115} 116