1 ; RUN: opt < %s -instsimplify -S | FileCheck %s 2 ; RUN: opt < %s -passes=instsimplify -S | FileCheck %s 3 4 declare {i8, i1} @llvm.uadd.with.overflow.i8(i8 %a, i8 %b) 5 declare {i8, i1} @llvm.usub.with.overflow.i8(i8 %a, i8 %b) 6 declare {i8, i1} @llvm.ssub.with.overflow.i8(i8 %a, i8 %b) 7 declare {i8, i1} @llvm.umul.with.overflow.i8(i8 %a, i8 %b) 8 9 define i1 @test_uadd1() { 10 ; CHECK-LABEL: @test_uadd1( 11 %x = call {i8, i1} @llvm.uadd.with.overflow.i8(i8 254, i8 3) 12 %overflow = extractvalue {i8, i1} %x, 1 13 ret i1 %overflow 14 ; CHECK-NEXT: ret i1 true 15 } 16 17 define i8 @test_uadd2() { 18 ; CHECK-LABEL: @test_uadd2( 19 %x = call {i8, i1} @llvm.uadd.with.overflow.i8(i8 254, i8 44) 20 %result = extractvalue {i8, i1} %x, 0 21 ret i8 %result 22 ; CHECK-NEXT: ret i8 42 23 } 24 25 define {i8, i1} @test_usub1(i8 %V) { 26 ; CHECK-LABEL: @test_usub1( 27 %x = call {i8, i1} @llvm.usub.with.overflow.i8(i8 %V, i8 %V) 28 ret {i8, i1} %x 29 ; CHECK-NEXT: ret { i8, i1 } zeroinitializer 30 } 31 32 define {i8, i1} @test_ssub1(i8 %V) { 33 ; CHECK-LABEL: @test_ssub1( 34 %x = call {i8, i1} @llvm.ssub.with.overflow.i8(i8 %V, i8 %V) 35 ret {i8, i1} %x 36 ; CHECK-NEXT: ret { i8, i1 } zeroinitializer 37 } 38 39 define {i8, i1} @test_umul1(i8 %V) { 40 ; CHECK-LABEL: @test_umul1( 41 %x = call {i8, i1} @llvm.umul.with.overflow.i8(i8 %V, i8 0) 42 ret {i8, i1} %x 43 ; CHECK-NEXT: ret { i8, i1 } zeroinitializer 44 } 45 46 declare i256 @llvm.cttz.i256(i256 %src, i1 %is_zero_undef) 47 48 define i256 @test_cttz() { 49 ; CHECK-LABEL: @test_cttz( 50 %x = call i256 @llvm.cttz.i256(i256 10, i1 false) 51 ret i256 %x 52 ; CHECK-NEXT: ret i256 1 53 } 54 55 declare i256 @llvm.ctpop.i256(i256 %src) 56 57 define i256 @test_ctpop() { 58 ; CHECK-LABEL: @test_ctpop( 59 %x = call i256 @llvm.ctpop.i256(i256 10) 60 ret i256 %x 61 ; CHECK-NEXT: ret i256 2 62 } 63 64 ; Test a non-intrinsic that we know about as a library call. 65 declare float @fabs(float %x) 66 67 define float @test_fabs_libcall() { 68 ; CHECK-LABEL: @test_fabs_libcall( 69 70 %x = call float @fabs(float -42.0) 71 ; This is still a real function call, so instsimplify won't nuke it -- other 72 ; passes have to do that. 73 ; CHECK-NEXT: call float @fabs 74 75 ret float %x 76 ; CHECK-NEXT: ret float 4.2{{0+}}e+01 77 } 78 79 80 declare float @llvm.fabs.f32(float) nounwind readnone 81 declare float @llvm.floor.f32(float) nounwind readnone 82 declare float @llvm.ceil.f32(float) nounwind readnone 83 declare float @llvm.trunc.f32(float) nounwind readnone 84 declare float @llvm.rint.f32(float) nounwind readnone 85 declare float @llvm.nearbyint.f32(float) nounwind readnone 86 87 ; Test idempotent intrinsics 88 define float @test_idempotence(float %a) { 89 ; CHECK-LABEL: @test_idempotence( 90 91 ; CHECK: fabs 92 ; CHECK-NOT: fabs 93 %a0 = call float @llvm.fabs.f32(float %a) 94 %a1 = call float @llvm.fabs.f32(float %a0) 95 96 ; CHECK: floor 97 ; CHECK-NOT: floor 98 %b0 = call float @llvm.floor.f32(float %a) 99 %b1 = call float @llvm.floor.f32(float %b0) 100 101 ; CHECK: ceil 102 ; CHECK-NOT: ceil 103 %c0 = call float @llvm.ceil.f32(float %a) 104 %c1 = call float @llvm.ceil.f32(float %c0) 105 106 ; CHECK: trunc 107 ; CHECK-NOT: trunc 108 %d0 = call float @llvm.trunc.f32(float %a) 109 %d1 = call float @llvm.trunc.f32(float %d0) 110 111 ; CHECK: rint 112 ; CHECK-NOT: rint 113 %e0 = call float @llvm.rint.f32(float %a) 114 %e1 = call float @llvm.rint.f32(float %e0) 115 116 ; CHECK: nearbyint 117 ; CHECK-NOT: nearbyint 118 %f0 = call float @llvm.nearbyint.f32(float %a) 119 %f1 = call float @llvm.nearbyint.f32(float %f0) 120 121 %r0 = fadd float %a1, %b1 122 %r1 = fadd float %r0, %c1 123 %r2 = fadd float %r1, %d1 124 %r3 = fadd float %r2, %e1 125 %r4 = fadd float %r3, %f1 126 127 ret float %r4 128 } 129 130 define i8* @operator_new() { 131 entry: 132 %call = tail call noalias i8* @_Znwm(i64 8) 133 %cmp = icmp eq i8* %call, null 134 br i1 %cmp, label %cast.end, label %cast.notnull 135 136 cast.notnull: ; preds = %entry 137 %add.ptr = getelementptr inbounds i8, i8* %call, i64 4 138 br label %cast.end 139 140 cast.end: ; preds = %cast.notnull, %entry 141 %cast.result = phi i8* [ %add.ptr, %cast.notnull ], [ null, %entry ] 142 ret i8* %cast.result 143 144 ; CHECK-LABEL: @operator_new 145 ; CHECK: br i1 false, label %cast.end, label %cast.notnull 146 } 147 148 declare nonnull noalias i8* @_Znwm(i64) 149 150 %"struct.std::nothrow_t" = type { i8 } 151 @_ZSt7nothrow = external global %"struct.std::nothrow_t" 152 153 define i8* @operator_new_nothrow_t() { 154 entry: 155 %call = tail call noalias i8* @_ZnamRKSt9nothrow_t(i64 8, %"struct.std::nothrow_t"* @_ZSt7nothrow) 156 %cmp = icmp eq i8* %call, null 157 br i1 %cmp, label %cast.end, label %cast.notnull 158 159 cast.notnull: ; preds = %entry 160 %add.ptr = getelementptr inbounds i8, i8* %call, i64 4 161 br label %cast.end 162 163 cast.end: ; preds = %cast.notnull, %entry 164 %cast.result = phi i8* [ %add.ptr, %cast.notnull ], [ null, %entry ] 165 ret i8* %cast.result 166 167 ; CHECK-LABEL: @operator_new_nothrow_t 168 ; CHECK: br i1 %cmp, label %cast.end, label %cast.notnull 169 } 170 171 declare i8* @_ZnamRKSt9nothrow_t(i64, %"struct.std::nothrow_t"*) nounwind 172 173 define i8* @malloc_can_return_null() { 174 entry: 175 %call = tail call noalias i8* @malloc(i64 8) 176 %cmp = icmp eq i8* %call, null 177 br i1 %cmp, label %cast.end, label %cast.notnull 178 179 cast.notnull: ; preds = %entry 180 %add.ptr = getelementptr inbounds i8, i8* %call, i64 4 181 br label %cast.end 182 183 cast.end: ; preds = %cast.notnull, %entry 184 %cast.result = phi i8* [ %add.ptr, %cast.notnull ], [ null, %entry ] 185 ret i8* %cast.result 186 187 ; CHECK-LABEL: @malloc_can_return_null 188 ; CHECK: br i1 %cmp, label %cast.end, label %cast.notnull 189 } 190 191 define i32 @call_null() { 192 entry: 193 %call = call i32 null() 194 ret i32 %call 195 } 196 ; CHECK-LABEL: define i32 @call_null( 197 ; CHECK: ret i32 undef 198 199 define i32 @call_undef() { 200 entry: 201 %call = call i32 undef() 202 ret i32 %call 203 } 204 ; CHECK-LABEL: define i32 @call_undef( 205 ; CHECK: ret i32 undef 206 207 @GV = private constant [8 x i32] [i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49] 208 209 define <8 x i32> @partial_masked_load() { 210 ; CHECK-LABEL: @partial_masked_load( 211 ; CHECK: ret <8 x i32> <i32 undef, i32 undef, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47> 212 %masked.load = call <8 x i32> @llvm.masked.load.v8i32.p0v8i32(<8 x i32>* bitcast (i32* getelementptr ([8 x i32], [8 x i32]* @GV, i64 0, i64 -2) to <8 x i32>*), i32 4, <8 x i1> <i1 false, i1 false, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true>, <8 x i32> undef) 213 ret <8 x i32> %masked.load 214 } 215 216 define <8 x i32> @masked_load_undef_mask(<8 x i32>* %V) { 217 ; CHECK-LABEL: @masked_load_undef_mask( 218 ; CHECK: ret <8 x i32> <i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0> 219 %masked.load = call <8 x i32> @llvm.masked.load.v8i32.p0v8i32(<8 x i32>* %V, i32 4, <8 x i1> undef, <8 x i32> <i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0>) 220 ret <8 x i32> %masked.load 221 } 222 223 declare noalias i8* @malloc(i64) 224 225 declare <8 x i32> @llvm.masked.load.v8i32.p0v8i32(<8 x i32>*, i32, <8 x i1>, <8 x i32>) 226