forked from OSchip/llvm-project
378 lines
10 KiB
LLVM
378 lines
10 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt %s -instcombine -S | FileCheck %s
|
|
|
|
declare void @use8(i8)
|
|
|
|
; Constant can be freely negated.
|
|
define i8 @t0(i8 %x) {
|
|
; CHECK-LABEL: @t0(
|
|
; CHECK-NEXT: [[T0:%.*]] = add i8 [[X:%.*]], 42
|
|
; CHECK-NEXT: ret i8 [[T0]]
|
|
;
|
|
%t0 = sub i8 %x, -42
|
|
ret i8 %t0
|
|
}
|
|
|
|
; Negation can be negated for free
|
|
define i8 @t1(i8 %x, i8 %y) {
|
|
; CHECK-LABEL: @t1(
|
|
; CHECK-NEXT: [[T0:%.*]] = sub i8 0, [[Y:%.*]]
|
|
; CHECK-NEXT: call void @use8(i8 [[T0]])
|
|
; CHECK-NEXT: [[T1:%.*]] = add i8 [[X:%.*]], [[Y]]
|
|
; CHECK-NEXT: ret i8 [[T1]]
|
|
;
|
|
%t0 = sub i8 0, %y
|
|
call void @use8(i8 %t0)
|
|
%t1 = sub i8 %x, %t0
|
|
ret i8 %t1
|
|
}
|
|
|
|
; Shift-left can be negated if all uses can be updated
|
|
define i8 @t2(i8 %x, i8 %y) {
|
|
; CHECK-LABEL: @t2(
|
|
; CHECK-NEXT: [[T0:%.*]] = shl i8 -42, [[Y:%.*]]
|
|
; CHECK-NEXT: [[T1:%.*]] = sub i8 [[X:%.*]], [[T0]]
|
|
; CHECK-NEXT: ret i8 [[T1]]
|
|
;
|
|
%t0 = shl i8 -42, %y
|
|
%t1 = sub i8 %x, %t0
|
|
ret i8 %t1
|
|
}
|
|
define i8 @n2(i8 %x, i8 %y) {
|
|
; CHECK-LABEL: @n2(
|
|
; CHECK-NEXT: [[T0:%.*]] = shl i8 -42, [[Y:%.*]]
|
|
; CHECK-NEXT: call void @use8(i8 [[T0]])
|
|
; CHECK-NEXT: [[T1:%.*]] = sub i8 [[X:%.*]], [[T0]]
|
|
; CHECK-NEXT: ret i8 [[T1]]
|
|
;
|
|
%t0 = shl i8 -42, %y
|
|
call void @use8(i8 %t0)
|
|
%t1 = sub i8 %x, %t0
|
|
ret i8 %t1
|
|
}
|
|
define i8 @t3(i8 %x, i8 %y, i8 %z) {
|
|
; CHECK-LABEL: @t3(
|
|
; CHECK-NEXT: [[T0:%.*]] = sub i8 0, [[Z:%.*]]
|
|
; CHECK-NEXT: call void @use8(i8 [[T0]])
|
|
; CHECK-NEXT: [[T1:%.*]] = shl i8 [[T0]], [[Y:%.*]]
|
|
; CHECK-NEXT: [[T2:%.*]] = sub i8 [[X:%.*]], [[T1]]
|
|
; CHECK-NEXT: ret i8 [[T2]]
|
|
;
|
|
%t0 = sub i8 0, %z
|
|
call void @use8(i8 %t0)
|
|
%t1 = shl i8 %t0, %y
|
|
%t2 = sub i8 %x, %t1
|
|
ret i8 %t2
|
|
}
|
|
define i8 @n3(i8 %x, i8 %y, i8 %z) {
|
|
; CHECK-LABEL: @n3(
|
|
; CHECK-NEXT: [[T0:%.*]] = sub i8 0, [[Z:%.*]]
|
|
; CHECK-NEXT: call void @use8(i8 [[T0]])
|
|
; CHECK-NEXT: [[T1:%.*]] = shl i8 [[T0]], [[Y:%.*]]
|
|
; CHECK-NEXT: call void @use8(i8 [[T1]])
|
|
; CHECK-NEXT: [[T2:%.*]] = sub i8 [[X:%.*]], [[T1]]
|
|
; CHECK-NEXT: ret i8 [[T2]]
|
|
;
|
|
%t0 = sub i8 0, %z
|
|
call void @use8(i8 %t0)
|
|
%t1 = shl i8 %t0, %y
|
|
call void @use8(i8 %t1)
|
|
%t2 = sub i8 %x, %t1
|
|
ret i8 %t2
|
|
}
|
|
|
|
; Select can be negated if all it's operands can be negated and all the users of select can be updated
|
|
define i8 @t4(i8 %x, i1 %y) {
|
|
; CHECK-LABEL: @t4(
|
|
; CHECK-NEXT: [[T0:%.*]] = select i1 [[Y:%.*]], i8 -42, i8 44
|
|
; CHECK-NEXT: [[T1:%.*]] = sub i8 [[X:%.*]], [[T0]]
|
|
; CHECK-NEXT: ret i8 [[T1]]
|
|
;
|
|
%t0 = select i1 %y, i8 -42, i8 44
|
|
%t1 = sub i8 %x, %t0
|
|
ret i8 %t1
|
|
}
|
|
define i8 @n4(i8 %x, i1 %y) {
|
|
; CHECK-LABEL: @n4(
|
|
; CHECK-NEXT: [[T0:%.*]] = select i1 [[Y:%.*]], i8 -42, i8 44
|
|
; CHECK-NEXT: call void @use8(i8 [[T0]])
|
|
; CHECK-NEXT: [[T1:%.*]] = sub i8 [[X:%.*]], [[T0]]
|
|
; CHECK-NEXT: ret i8 [[T1]]
|
|
;
|
|
%t0 = select i1 %y, i8 -42, i8 44
|
|
call void @use8(i8 %t0)
|
|
%t1 = sub i8 %x, %t0
|
|
ret i8 %t1
|
|
}
|
|
define i8 @n5(i8 %x, i1 %y, i8 %z) {
|
|
; CHECK-LABEL: @n5(
|
|
; CHECK-NEXT: [[T0:%.*]] = select i1 [[Y:%.*]], i8 -42, i8 [[Z:%.*]]
|
|
; CHECK-NEXT: [[T1:%.*]] = sub i8 [[X:%.*]], [[T0]]
|
|
; CHECK-NEXT: ret i8 [[T1]]
|
|
;
|
|
%t0 = select i1 %y, i8 -42, i8 %z
|
|
%t1 = sub i8 %x, %t0
|
|
ret i8 %t1
|
|
}
|
|
define i8 @t6(i8 %x, i1 %y, i8 %z) {
|
|
; CHECK-LABEL: @t6(
|
|
; CHECK-NEXT: [[T0:%.*]] = sub i8 0, [[Z:%.*]]
|
|
; CHECK-NEXT: call void @use8(i8 [[T0]])
|
|
; CHECK-NEXT: [[T1:%.*]] = select i1 [[Y:%.*]], i8 -42, i8 [[T0]]
|
|
; CHECK-NEXT: [[T2:%.*]] = sub i8 [[X:%.*]], [[T1]]
|
|
; CHECK-NEXT: ret i8 [[T2]]
|
|
;
|
|
%t0 = sub i8 0, %z
|
|
call void @use8(i8 %t0)
|
|
%t1 = select i1 %y, i8 -42, i8 %t0
|
|
%t2 = sub i8 %x, %t1
|
|
ret i8 %t2
|
|
}
|
|
define i8 @t7(i8 %x, i1 %y, i8 %z) {
|
|
; CHECK-LABEL: @t7(
|
|
; CHECK-NEXT: [[T0:%.*]] = shl i8 1, [[Z:%.*]]
|
|
; CHECK-NEXT: [[T1:%.*]] = select i1 [[Y:%.*]], i8 0, i8 [[T0]]
|
|
; CHECK-NEXT: [[T2:%.*]] = sub i8 [[X:%.*]], [[T1]]
|
|
; CHECK-NEXT: ret i8 [[T2]]
|
|
;
|
|
%t0 = shl i8 1, %z
|
|
%t1 = select i1 %y, i8 0, i8 %t0
|
|
%t2 = sub i8 %x, %t1
|
|
ret i8 %t2
|
|
}
|
|
define i8 @n8(i8 %x, i1 %y, i8 %z) {
|
|
; CHECK-LABEL: @n8(
|
|
; CHECK-NEXT: [[T0:%.*]] = shl i8 1, [[Z:%.*]]
|
|
; CHECK-NEXT: call void @use8(i8 [[T0]])
|
|
; CHECK-NEXT: [[T1:%.*]] = select i1 [[Y:%.*]], i8 0, i8 [[T0]]
|
|
; CHECK-NEXT: [[T2:%.*]] = sub i8 [[X:%.*]], [[T1]]
|
|
; CHECK-NEXT: ret i8 [[T2]]
|
|
;
|
|
%t0 = shl i8 1, %z
|
|
call void @use8(i8 %t0)
|
|
%t1 = select i1 %y, i8 0, i8 %t0
|
|
%t2 = sub i8 %x, %t1
|
|
ret i8 %t2
|
|
}
|
|
|
|
; Subtraction can be negated by swapping its operands.
|
|
; x - (y - z) -> x - y + z -> x + (z - y)
|
|
define i8 @t9(i8 %x, i8 %y) {
|
|
; CHECK-LABEL: @t9(
|
|
; CHECK-NEXT: [[T01:%.*]] = sub i8 [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: ret i8 [[T01]]
|
|
;
|
|
%t0 = sub i8 %y, %x
|
|
%t1 = sub i8 0, %t0
|
|
ret i8 %t1
|
|
}
|
|
define i8 @n10(i8 %x, i8 %y, i8 %z) {
|
|
; CHECK-LABEL: @n10(
|
|
; CHECK-NEXT: [[T0:%.*]] = sub i8 [[Y:%.*]], [[X:%.*]]
|
|
; CHECK-NEXT: call void @use8(i8 [[T0]])
|
|
; CHECK-NEXT: [[T1:%.*]] = sub i8 0, [[T0]]
|
|
; CHECK-NEXT: ret i8 [[T1]]
|
|
;
|
|
%t0 = sub i8 %y, %x
|
|
call void @use8(i8 %t0)
|
|
%t1 = sub i8 0, %t0
|
|
ret i8 %t1
|
|
}
|
|
|
|
; Addition can be negated if both operands can be negated
|
|
; x - (y + z) -> x - y - z -> x + ((-y) + (-z)))
|
|
define i8 @t12(i8 %x, i8 %y, i8 %z) {
|
|
; CHECK-LABEL: @t12(
|
|
; CHECK-NEXT: [[T0:%.*]] = sub i8 0, [[Y:%.*]]
|
|
; CHECK-NEXT: call void @use8(i8 [[T0]])
|
|
; CHECK-NEXT: [[T1:%.*]] = sub i8 0, [[Z:%.*]]
|
|
; CHECK-NEXT: call void @use8(i8 [[T1]])
|
|
; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[Y]], [[Z]]
|
|
; CHECK-NEXT: [[T3:%.*]] = add i8 [[TMP1]], [[X:%.*]]
|
|
; CHECK-NEXT: ret i8 [[T3]]
|
|
;
|
|
%t0 = sub i8 0, %y
|
|
call void @use8(i8 %t0)
|
|
%t1 = sub i8 0, %z
|
|
call void @use8(i8 %t1)
|
|
%t2 = add i8 %t0, %t1
|
|
%t3 = sub i8 %x, %t2
|
|
ret i8 %t3
|
|
}
|
|
define i8 @n13(i8 %x, i8 %y, i8 %z) {
|
|
; CHECK-LABEL: @n13(
|
|
; CHECK-NEXT: [[T0:%.*]] = sub i8 0, [[Y:%.*]]
|
|
; CHECK-NEXT: call void @use8(i8 [[T0]])
|
|
; CHECK-NEXT: [[T11:%.*]] = sub i8 [[Y]], [[Z:%.*]]
|
|
; CHECK-NEXT: [[T2:%.*]] = add i8 [[T11]], [[X:%.*]]
|
|
; CHECK-NEXT: ret i8 [[T2]]
|
|
;
|
|
%t0 = sub i8 0, %y
|
|
call void @use8(i8 %t0)
|
|
%t1 = add i8 %t0, %z
|
|
%t2 = sub i8 %x, %t1
|
|
ret i8 %t2
|
|
}
|
|
define i8 @n14(i8 %x, i8 %y, i8 %z) {
|
|
; CHECK-LABEL: @n14(
|
|
; CHECK-NEXT: [[T0:%.*]] = sub i8 0, [[Y:%.*]]
|
|
; CHECK-NEXT: call void @use8(i8 [[T0]])
|
|
; CHECK-NEXT: [[T1:%.*]] = sub i8 0, [[Z:%.*]]
|
|
; CHECK-NEXT: call void @use8(i8 [[T1]])
|
|
; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[Y]], [[Z]]
|
|
; CHECK-NEXT: [[T2:%.*]] = sub i8 0, [[TMP1]]
|
|
; CHECK-NEXT: call void @use8(i8 [[T2]])
|
|
; CHECK-NEXT: [[T3:%.*]] = add i8 [[TMP1]], [[X:%.*]]
|
|
; CHECK-NEXT: ret i8 [[T3]]
|
|
;
|
|
%t0 = sub i8 0, %y
|
|
call void @use8(i8 %t0)
|
|
%t1 = sub i8 0, %z
|
|
call void @use8(i8 %t1)
|
|
%t2 = add i8 %t0, %t1
|
|
call void @use8(i8 %t2)
|
|
%t3 = sub i8 %x, %t2
|
|
ret i8 %t3
|
|
}
|
|
|
|
; Multiplication can be negated if either one of operands can be negated
|
|
; x - (y * z) -> x + ((-y) * z) or x + ((-z) * y)
|
|
define i8 @t15(i8 %x, i8 %y, i8 %z) {
|
|
; CHECK-LABEL: @t15(
|
|
; CHECK-NEXT: [[T0:%.*]] = sub i8 0, [[Y:%.*]]
|
|
; CHECK-NEXT: call void @use8(i8 [[T0]])
|
|
; CHECK-NEXT: [[TMP1:%.*]] = mul i8 [[Z:%.*]], [[Y]]
|
|
; CHECK-NEXT: [[T2:%.*]] = add i8 [[TMP1]], [[X:%.*]]
|
|
; CHECK-NEXT: ret i8 [[T2]]
|
|
;
|
|
%t0 = sub i8 0, %y
|
|
call void @use8(i8 %t0)
|
|
%t1 = mul i8 %t0, %z
|
|
%t2 = sub i8 %x, %t1
|
|
ret i8 %t2
|
|
}
|
|
define i8 @n16(i8 %x, i8 %y, i8 %z) {
|
|
; CHECK-LABEL: @n16(
|
|
; CHECK-NEXT: [[T0:%.*]] = sub i8 0, [[Y:%.*]]
|
|
; CHECK-NEXT: call void @use8(i8 [[T0]])
|
|
; CHECK-NEXT: [[T1:%.*]] = mul i8 [[T0]], [[Z:%.*]]
|
|
; CHECK-NEXT: call void @use8(i8 [[T1]])
|
|
; CHECK-NEXT: [[T2:%.*]] = sub i8 [[X:%.*]], [[T1]]
|
|
; CHECK-NEXT: ret i8 [[T2]]
|
|
;
|
|
%t0 = sub i8 0, %y
|
|
call void @use8(i8 %t0)
|
|
%t1 = mul i8 %t0, %z
|
|
call void @use8(i8 %t1)
|
|
%t2 = sub i8 %x, %t1
|
|
ret i8 %t2
|
|
}
|
|
|
|
; Phi can be negated if all incoming values can be negated
|
|
define i8 @t16(i1 %c, i8 %x) {
|
|
; CHECK-LABEL: @t16(
|
|
; CHECK-NEXT: begin:
|
|
; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]]
|
|
; CHECK: then:
|
|
; CHECK-NEXT: br label [[END:%.*]]
|
|
; CHECK: else:
|
|
; CHECK-NEXT: br label [[END]]
|
|
; CHECK: end:
|
|
; CHECK-NEXT: [[Z:%.*]] = phi i8 [ [[X:%.*]], [[THEN]] ], [ 42, [[ELSE]] ]
|
|
; CHECK-NEXT: ret i8 [[Z]]
|
|
;
|
|
begin:
|
|
br i1 %c, label %then, label %else
|
|
then:
|
|
%y = sub i8 0, %x
|
|
br label %end
|
|
else:
|
|
br label %end
|
|
end:
|
|
%z = phi i8 [ %y, %then], [ -42, %else ]
|
|
%n = sub i8 0, %z
|
|
ret i8 %n
|
|
}
|
|
define i8 @n17(i1 %c, i8 %x) {
|
|
; CHECK-LABEL: @n17(
|
|
; CHECK-NEXT: begin:
|
|
; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]]
|
|
; CHECK: then:
|
|
; CHECK-NEXT: [[Y:%.*]] = sub i8 0, [[X:%.*]]
|
|
; CHECK-NEXT: br label [[END:%.*]]
|
|
; CHECK: else:
|
|
; CHECK-NEXT: br label [[END]]
|
|
; CHECK: end:
|
|
; CHECK-NEXT: [[Z:%.*]] = phi i8 [ [[Y]], [[THEN]] ], [ -42, [[ELSE]] ]
|
|
; CHECK-NEXT: call void @use8(i8 [[Z]])
|
|
; CHECK-NEXT: [[N:%.*]] = sub i8 0, [[Z]]
|
|
; CHECK-NEXT: ret i8 [[N]]
|
|
;
|
|
begin:
|
|
br i1 %c, label %then, label %else
|
|
then:
|
|
%y = sub i8 0, %x
|
|
br label %end
|
|
else:
|
|
br label %end
|
|
end:
|
|
%z = phi i8 [ %y, %then], [ -42, %else ]
|
|
call void @use8(i8 %z)
|
|
%n = sub i8 0, %z
|
|
ret i8 %n
|
|
}
|
|
define i8 @n19(i1 %c, i8 %x, i8 %y) {
|
|
; CHECK-LABEL: @n19(
|
|
; CHECK-NEXT: begin:
|
|
; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]]
|
|
; CHECK: then:
|
|
; CHECK-NEXT: [[Z:%.*]] = sub i8 0, [[X:%.*]]
|
|
; CHECK-NEXT: br label [[END:%.*]]
|
|
; CHECK: else:
|
|
; CHECK-NEXT: br label [[END]]
|
|
; CHECK: end:
|
|
; CHECK-NEXT: [[R:%.*]] = phi i8 [ [[Z]], [[THEN]] ], [ [[Y:%.*]], [[ELSE]] ]
|
|
; CHECK-NEXT: [[N:%.*]] = sub i8 0, [[R]]
|
|
; CHECK-NEXT: ret i8 [[N]]
|
|
;
|
|
begin:
|
|
br i1 %c, label %then, label %else
|
|
then:
|
|
%z = sub i8 0, %x
|
|
br label %end
|
|
else:
|
|
br label %end
|
|
end:
|
|
%r = phi i8 [ %z, %then], [ %y, %else ]
|
|
%n = sub i8 0, %r
|
|
ret i8 %n
|
|
}
|
|
|
|
; truncation can be negated if it's operand can be negated
|
|
define i8 @t20(i8 %x, i16 %y) {
|
|
; CHECK-LABEL: @t20(
|
|
; CHECK-NEXT: [[T0:%.*]] = shl i16 -42, [[Y:%.*]]
|
|
; CHECK-NEXT: [[T1:%.*]] = trunc i16 [[T0]] to i8
|
|
; CHECK-NEXT: [[T2:%.*]] = sub i8 [[X:%.*]], [[T1]]
|
|
; CHECK-NEXT: ret i8 [[T2]]
|
|
;
|
|
%t0 = shl i16 -42, %y
|
|
%t1 = trunc i16 %t0 to i8
|
|
%t2 = sub i8 %x, %t1
|
|
ret i8 %t2
|
|
}
|
|
define i8 @n21(i8 %x, i16 %y) {
|
|
; CHECK-LABEL: @n21(
|
|
; CHECK-NEXT: [[T0:%.*]] = shl i16 -42, [[Y:%.*]]
|
|
; CHECK-NEXT: [[T1:%.*]] = trunc i16 [[T0]] to i8
|
|
; CHECK-NEXT: call void @use8(i8 [[T1]])
|
|
; CHECK-NEXT: [[T2:%.*]] = sub i8 [[X:%.*]], [[T1]]
|
|
; CHECK-NEXT: ret i8 [[T2]]
|
|
;
|
|
%t0 = shl i16 -42, %y
|
|
%t1 = trunc i16 %t0 to i8
|
|
call void @use8(i8 %t1)
|
|
%t2 = sub i8 %x, %t1
|
|
ret i8 %t2
|
|
}
|