
Should cover most of the tests for GVN, GVNHoist, GVNSink, GlobalOpt, GlobalSplit, InstCombine, Reassociate, SROA and TailCallElim that had not been updated earlier.
112 lines
3.3 KiB
LLVM
112 lines
3.3 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt -passes=gvn -S < %s | FileCheck %s
|
|
|
|
declare void @use(i32, i32)
|
|
|
|
define void @binop(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: @binop(
|
|
; CHECK-NEXT: [[ADD1:%.*]] = add i32 [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: call void @use(i32 [[ADD1]], i32 [[ADD1]])
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%add1 = add i32 %x, %y
|
|
%add2 = add i32 %y, %x
|
|
call void @use(i32 %add1, i32 %add2)
|
|
ret void
|
|
}
|
|
|
|
declare void @vse(i1, i1)
|
|
|
|
define void @cmp(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: @cmp(
|
|
; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: call void @vse(i1 [[CMP1]], i1 [[CMP1]])
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%cmp1 = icmp ult i32 %x, %y
|
|
%cmp2 = icmp ugt i32 %y, %x
|
|
call void @vse(i1 %cmp1, i1 %cmp2)
|
|
ret void
|
|
}
|
|
|
|
declare i32 @llvm.umax.i32(i32, i32)
|
|
|
|
define void @intrinsic(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: @intrinsic(
|
|
; CHECK-NEXT: [[M1:%.*]] = call i32 @llvm.umax.i32(i32 [[X:%.*]], i32 [[Y:%.*]])
|
|
; CHECK-NEXT: call void @use(i32 [[M1]], i32 [[M1]])
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%m1 = call i32 @llvm.umax.i32(i32 %x, i32 %y)
|
|
%m2 = call i32 @llvm.umax.i32(i32 %y, i32 %x)
|
|
call void @use(i32 %m1, i32 %m2)
|
|
ret void
|
|
}
|
|
|
|
declare { i32, i1 } @llvm.umul.with.overflow.i32(i32, i32)
|
|
|
|
define { i32, i1 } @intrinsic2(i32 %x, i32 %y, i1 %cond) {
|
|
; CHECK-LABEL: @intrinsic2(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
|
|
; CHECK: if.then:
|
|
; CHECK-NEXT: unreachable
|
|
; CHECK: if.end:
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 0, [[Y:%.*]]
|
|
; CHECK-NEXT: [[UMUL:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 [[X:%.*]], i32 [[Y]])
|
|
; CHECK-NEXT: ret { i32, i1 } [[UMUL]]
|
|
;
|
|
entry:
|
|
br i1 %cond, label %if.then, label %if.end
|
|
|
|
if.then:
|
|
unreachable
|
|
|
|
if.end:
|
|
%cmp = icmp eq i32 0, %y
|
|
%umul = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %x, i32 %y)
|
|
ret { i32, i1 } %umul
|
|
}
|
|
|
|
declare i16 @llvm.smul.fix.i16(i16, i16, i32)
|
|
declare i16 @llvm.umul.fix.i16(i16, i16, i32)
|
|
|
|
define i16 @intrinsic_3_args(i16 %x, i16 %y) {
|
|
; CHECK-LABEL: @intrinsic_3_args(
|
|
; CHECK-NEXT: [[M1:%.*]] = call i16 @llvm.smul.fix.i16(i16 [[X:%.*]], i16 [[Y:%.*]], i32 1)
|
|
; CHECK-NEXT: ret i16 0
|
|
;
|
|
%m1 = call i16 @llvm.smul.fix.i16(i16 %x, i16 %y, i32 1)
|
|
%m2 = call i16 @llvm.smul.fix.i16(i16 %y, i16 %x, i32 1)
|
|
%r = sub i16 %m1, %m2
|
|
ret i16 %r
|
|
}
|
|
|
|
; Negative test - 3rd arg is different
|
|
|
|
define i16 @intrinsic_3_args_not_same(i16 %x, i16 %y) {
|
|
; CHECK-LABEL: @intrinsic_3_args_not_same(
|
|
; CHECK-NEXT: [[M1:%.*]] = call i16 @llvm.umul.fix.i16(i16 [[X:%.*]], i16 [[Y:%.*]], i32 2)
|
|
; CHECK-NEXT: [[M2:%.*]] = call i16 @llvm.umul.fix.i16(i16 [[Y]], i16 [[X]], i32 1)
|
|
; CHECK-NEXT: [[R:%.*]] = sub i16 [[M1]], [[M2]]
|
|
; CHECK-NEXT: ret i16 [[R]]
|
|
;
|
|
%m1 = call i16 @llvm.umul.fix.i16(i16 %x, i16 %y, i32 2)
|
|
%m2 = call i16 @llvm.umul.fix.i16(i16 %y, i16 %x, i32 1)
|
|
%r = sub i16 %m1, %m2
|
|
ret i16 %r
|
|
}
|
|
|
|
declare float @llvm.fma.f32(float, float, float)
|
|
|
|
define float @fma(float %x, float %y) {
|
|
; CHECK-LABEL: @fma(
|
|
; CHECK-NEXT: [[M1:%.*]] = call float @llvm.fma.f32(float [[X:%.*]], float [[Y:%.*]], float 1.000000e+00)
|
|
; CHECK-NEXT: ret float 1.000000e+00
|
|
;
|
|
%m1 = call float @llvm.fma.f32(float %x, float %y, float 1.0)
|
|
%m2 = call float @llvm.fma.f32(float %y, float %x, float 1.0)
|
|
%r = fdiv nnan float %m1, %m2
|
|
ret float %r
|
|
}
|