1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 18:54:02 +01:00
llvm-mirror/test/Transforms/InstCombine/operand-complexity.ll
Simon Moll 24a623a765 [instcombine] remove fsub to fneg hacks; only emit fneg
Summary: Rewrite the fsub-0.0 idiom to fneg and always emit fneg for fp
negation. This also extends the scalarization cost in instcombine for unary
operators to result in the same IR rewrites for fneg as for the idiom.

Reviewed By: cameron.mcinally

Differential Revision: https://reviews.llvm.org/D75467
2020-03-10 16:57:02 +01:00

167 lines
5.6 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -instcombine -S | FileCheck %s
; 'Negate' is considered less complex than a normal binop, so the xor should have the binop as the first operand.
define i8 @neg(i8 %x) {
; CHECK-LABEL: @neg(
; CHECK-NEXT: [[BO:%.*]] = udiv i8 [[X:%.*]], 42
; CHECK-NEXT: [[NEGX:%.*]] = sub i8 0, [[X]]
; CHECK-NEXT: [[R:%.*]] = xor i8 [[BO]], [[NEGX]]
; CHECK-NEXT: ret i8 [[R]]
;
%bo = udiv i8 %x, 42
%negx = sub i8 0, %x
%r = xor i8 %negx, %bo
ret i8 %r
}
define <2 x i8> @neg_vec(<2 x i8> %x) {
; CHECK-LABEL: @neg_vec(
; CHECK-NEXT: [[BO:%.*]] = udiv <2 x i8> [[X:%.*]], <i8 42, i8 -42>
; CHECK-NEXT: [[NEGX:%.*]] = sub <2 x i8> zeroinitializer, [[X]]
; CHECK-NEXT: [[R:%.*]] = xor <2 x i8> [[BO]], [[NEGX]]
; CHECK-NEXT: ret <2 x i8> [[R]]
;
%bo = udiv <2 x i8> %x, <i8 42, i8 -42>
%negx = sub <2 x i8> <i8 0, i8 0>, %x
%r = xor <2 x i8> %negx, %bo
ret <2 x i8> %r
}
define <2 x i8> @neg_vec_undef(<2 x i8> %x) {
; CHECK-LABEL: @neg_vec_undef(
; CHECK-NEXT: [[BO:%.*]] = udiv <2 x i8> [[X:%.*]], <i8 42, i8 -42>
; CHECK-NEXT: [[NEGX:%.*]] = sub <2 x i8> <i8 0, i8 undef>, [[X]]
; CHECK-NEXT: [[R:%.*]] = xor <2 x i8> [[BO]], [[NEGX]]
; CHECK-NEXT: ret <2 x i8> [[R]]
;
%bo = udiv <2 x i8> %x, <i8 42, i8 -42>
%negx = sub <2 x i8> <i8 0, i8 undef>, %x
%r = xor <2 x i8> %negx, %bo
ret <2 x i8> %r
}
; 'Not' is considered less complex than a normal binop, so the mul should have the binop as the first operand.
define i8 @not(i8 %x) {
; CHECK-LABEL: @not(
; CHECK-NEXT: [[BO:%.*]] = udiv i8 [[X:%.*]], 42
; CHECK-NEXT: [[NOTX:%.*]] = xor i8 [[X]], -1
; CHECK-NEXT: [[R:%.*]] = mul i8 [[BO]], [[NOTX]]
; CHECK-NEXT: ret i8 [[R]]
;
%bo = udiv i8 %x, 42
%notx = xor i8 -1, %x
%r = mul i8 %notx, %bo
ret i8 %r
}
define <2 x i8> @not_vec(<2 x i8> %x) {
; CHECK-LABEL: @not_vec(
; CHECK-NEXT: [[BO:%.*]] = udiv <2 x i8> [[X:%.*]], <i8 42, i8 -42>
; CHECK-NEXT: [[NOTX:%.*]] = xor <2 x i8> [[X]], <i8 -1, i8 -1>
; CHECK-NEXT: [[R:%.*]] = mul <2 x i8> [[BO]], [[NOTX]]
; CHECK-NEXT: ret <2 x i8> [[R]]
;
%bo = udiv <2 x i8> %x, <i8 42, i8 -42>
%notx = xor <2 x i8> <i8 -1, i8 -1>, %x
%r = mul <2 x i8> %notx, %bo
ret <2 x i8> %r
}
define <2 x i8> @not_vec_undef(<2 x i8> %x) {
; CHECK-LABEL: @not_vec_undef(
; CHECK-NEXT: [[BO:%.*]] = udiv <2 x i8> [[X:%.*]], <i8 42, i8 -42>
; CHECK-NEXT: [[NOTX:%.*]] = xor <2 x i8> [[X]], <i8 -1, i8 undef>
; CHECK-NEXT: [[R:%.*]] = mul <2 x i8> [[BO]], [[NOTX]]
; CHECK-NEXT: ret <2 x i8> [[R]]
;
%bo = udiv <2 x i8> %x, <i8 42, i8 -42>
%notx = xor <2 x i8> <i8 -1, i8 undef>, %x
%r = mul <2 x i8> %notx, %bo
ret <2 x i8> %r
}
; 'Fneg' is considered less complex than a normal binop, so the fmul should have the binop as the first operand.
; Extra uses are required to ensure that the fneg is not canonicalized after the fmul.
declare void @use(float)
declare void @use_vec(<2 x float>)
define float @fneg(float %x) {
; CHECK-LABEL: @fneg(
; CHECK-NEXT: [[BO:%.*]] = fdiv float [[X:%.*]], 4.200000e+01
; CHECK-NEXT: [[FNEGX:%.*]] = fneg float [[X]]
; CHECK-NEXT: [[R:%.*]] = fmul float [[BO]], [[FNEGX]]
; CHECK-NEXT: call void @use(float [[FNEGX]])
; CHECK-NEXT: ret float [[R]]
;
%bo = fdiv float %x, 42.0
%fnegx = fsub float -0.0, %x
%r = fmul float %fnegx, %bo
call void @use(float %fnegx)
ret float %r
}
define float @unary_fneg(float %x) {
; CHECK-LABEL: @unary_fneg(
; CHECK-NEXT: [[BO:%.*]] = fdiv float [[X:%.*]], 4.200000e+01
; CHECK-NEXT: [[FNEGX:%.*]] = fneg float [[X]]
; CHECK-NEXT: [[R:%.*]] = fmul float [[BO]], [[FNEGX]]
; CHECK-NEXT: call void @use(float [[FNEGX]])
; CHECK-NEXT: ret float [[R]]
;
%bo = fdiv float %x, 42.0
%fnegx = fneg float %x
%r = fmul float %fnegx, %bo
call void @use(float %fnegx)
ret float %r
}
define <2 x float> @fneg_vec(<2 x float> %x) {
; CHECK-LABEL: @fneg_vec(
; CHECK-NEXT: [[BO:%.*]] = fdiv <2 x float> [[X:%.*]], <float 4.200000e+01, float -4.200000e+01>
; CHECK-NEXT: [[FNEGX:%.*]] = fneg <2 x float> [[X]]
; CHECK-NEXT: [[R:%.*]] = fmul <2 x float> [[BO]], [[FNEGX]]
; CHECK-NEXT: call void @use_vec(<2 x float> [[FNEGX]])
; CHECK-NEXT: ret <2 x float> [[R]]
;
%bo = fdiv <2 x float> %x, <float 42.0, float -42.0>
%fnegx = fsub <2 x float> <float -0.0, float -0.0>, %x
%r = fmul <2 x float> %fnegx, %bo
call void @use_vec(<2 x float> %fnegx)
ret <2 x float> %r
}
define <2 x float> @fneg_vec_undef(<2 x float> %x) {
; CHECK-LABEL: @fneg_vec_undef(
; CHECK-NEXT: [[BO:%.*]] = fdiv <2 x float> [[X:%.*]], <float 4.200000e+01, float -4.200000e+01>
; CHECK-NEXT: [[FNEGX:%.*]] = fneg <2 x float> [[X]]
; CHECK-NEXT: [[R:%.*]] = fmul <2 x float> [[BO]], [[FNEGX]]
; CHECK-NEXT: call void @use_vec(<2 x float> [[FNEGX]])
; CHECK-NEXT: ret <2 x float> [[R]]
;
%bo = fdiv <2 x float> %x, <float 42.0, float -42.0>
%fnegx = fsub <2 x float> <float -0.0, float undef>, %x
%r = fmul <2 x float> %fnegx, %bo
call void @use_vec(<2 x float> %fnegx)
ret <2 x float> %r
}
define <2 x float> @unary_fneg_vec(<2 x float> %x) {
; CHECK-LABEL: @unary_fneg_vec(
; CHECK-NEXT: [[BO:%.*]] = fdiv <2 x float> [[X:%.*]], <float 4.200000e+01, float -4.200000e+01>
; CHECK-NEXT: [[FNEGX:%.*]] = fneg <2 x float> [[X]]
; CHECK-NEXT: [[R:%.*]] = fmul <2 x float> [[BO]], [[FNEGX]]
; CHECK-NEXT: call void @use_vec(<2 x float> [[FNEGX]])
; CHECK-NEXT: ret <2 x float> [[R]]
;
%bo = fdiv <2 x float> %x, <float 42.0, float -42.0>
%fnegx = fneg <2 x float> %x
%r = fmul <2 x float> %fnegx, %bo
call void @use_vec(<2 x float> %fnegx)
ret <2 x float> %r
}