1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc < %s -mtriple=x86_64-- | FileCheck %s 3 4%struct.obj = type { i64 } 5 6define dso_local void @_Z7releaseP3obj(%struct.obj* nocapture %o) nounwind uwtable ssp { 7; CHECK-LABEL: _Z7releaseP3obj: 8; CHECK: # %bb.0: # %entry 9; CHECK-NEXT: decq (%rdi) 10; CHECK-NEXT: je .LBB0_2 11; CHECK-NEXT: # %bb.1: # %return 12; CHECK-NEXT: retq 13; CHECK-NEXT: .LBB0_2: # %if.end 14; CHECK-NEXT: jmp free # TAILCALL 15entry: 16 %refcnt = getelementptr inbounds %struct.obj, %struct.obj* %o, i64 0, i32 0 17 %0 = load i64, i64* %refcnt, align 8 18 %dec = add i64 %0, -1 19 store i64 %dec, i64* %refcnt, align 8 20 %tobool = icmp eq i64 %dec, 0 21 br i1 %tobool, label %if.end, label %return 22 23if.end: ; preds = %entry 24 %1 = bitcast %struct.obj* %o to i8* 25 tail call void @free(i8* %1) 26 br label %return 27 28return: ; preds = %entry, %if.end 29 ret void 30} 31 32@c = common dso_local global i64 0, align 8 33@a = common dso_local global i32 0, align 4 34@.str = private unnamed_addr constant [5 x i8] c"%ld\0A\00", align 1 35@b = common dso_local global i32 0, align 4 36 37define dso_local i32 @test() nounwind uwtable ssp { 38; CHECK-LABEL: test: 39; CHECK: # %bb.0: # %entry 40; CHECK-NEXT: pushq %rax 41; CHECK-NEXT: .cfi_def_cfa_offset 16 42; CHECK-NEXT: movq c(%rip), %rsi 43; CHECK-NEXT: xorl %eax, %eax 44; CHECK-NEXT: decq %rsi 45; CHECK-NEXT: movq %rsi, c(%rip) 46; CHECK-NEXT: setne %al 47; CHECK-NEXT: movl %eax, a(%rip) 48; CHECK-NEXT: movl $.L.str, %edi 49; CHECK-NEXT: xorl %eax, %eax 50; CHECK-NEXT: callq printf@PLT 51; CHECK-NEXT: xorl %eax, %eax 52; CHECK-NEXT: popq %rcx 53; CHECK-NEXT: .cfi_def_cfa_offset 8 54; CHECK-NEXT: retq 55entry: 56%0 = load i64, i64* @c, align 8 57%dec.i = add nsw i64 %0, -1 58store i64 %dec.i, i64* @c, align 8 59%tobool.i = icmp ne i64 %dec.i, 0 60%lor.ext.i = zext i1 %tobool.i to i32 61store i32 %lor.ext.i, i32* @a, align 4 62%call = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0), i64 %dec.i) nounwind 63ret i32 0 64} 65 66define dso_local i32 @test2() nounwind uwtable ssp { 67; CHECK-LABEL: test2: 68; CHECK: # %bb.0: # %entry 69; CHECK-NEXT: pushq %rax 70; CHECK-NEXT: .cfi_def_cfa_offset 16 71; CHECK-NEXT: movq c(%rip), %rsi 72; CHECK-NEXT: xorl %eax, %eax 73; CHECK-NEXT: addq $-1, %rsi 74; CHECK-NEXT: setb %al 75; CHECK-NEXT: movq %rsi, c(%rip) 76; CHECK-NEXT: movl %eax, a(%rip) 77; CHECK-NEXT: movl $.L.str, %edi 78; CHECK-NEXT: xorl %eax, %eax 79; CHECK-NEXT: callq printf@PLT 80; CHECK-NEXT: xorl %eax, %eax 81; CHECK-NEXT: popq %rcx 82; CHECK-NEXT: .cfi_def_cfa_offset 8 83; CHECK-NEXT: retq 84entry: 85%0 = load i64, i64* @c, align 8 86%dec.i = add nsw i64 %0, -1 87store i64 %dec.i, i64* @c, align 8 88%tobool.i = icmp ne i64 %0, 0 89%lor.ext.i = zext i1 %tobool.i to i32 90store i32 %lor.ext.i, i32* @a, align 4 91%call = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0), i64 %dec.i) nounwind 92ret i32 0 93} 94 95declare i32 @printf(i8* nocapture, ...) nounwind 96 97declare dso_local void @free(i8* nocapture) nounwind 98 99%struct.obj2 = type { i64, i32, i16, i8 } 100 101declare dso_local void @other(%struct.obj2* ) nounwind; 102 103define dso_local void @example_dec(%struct.obj2* %o) nounwind uwtable ssp { 104; 64 bit dec 105; CHECK-LABEL: example_dec: 106; CHECK: # %bb.0: # %entry 107; CHECK-NEXT: decq (%rdi) 108; CHECK-NEXT: jne .LBB3_4 109; CHECK-NEXT: # %bb.1: # %if.end 110; CHECK-NEXT: decl 8(%rdi) 111; CHECK-NEXT: jne .LBB3_4 112; CHECK-NEXT: # %bb.2: # %if.end1 113; CHECK-NEXT: decw 12(%rdi) 114; CHECK-NEXT: jne .LBB3_4 115; CHECK-NEXT: # %bb.3: # %if.end2 116; CHECK-NEXT: decb 14(%rdi) 117; CHECK-NEXT: je .LBB3_5 118; CHECK-NEXT: .LBB3_4: # %return 119; CHECK-NEXT: retq 120; CHECK-NEXT: .LBB3_5: # %if.end4 121; CHECK-NEXT: jmp other # TAILCALL 122entry: 123 %s64 = getelementptr inbounds %struct.obj2, %struct.obj2* %o, i64 0, i32 0 124 %0 = load i64, i64* %s64, align 8 125 %dec = add i64 %0, -1 126 store i64 %dec, i64* %s64, align 8 127 %tobool = icmp eq i64 %dec, 0 128 br i1 %tobool, label %if.end, label %return 129 130; 32 bit dec 131if.end: 132 %s32 = getelementptr inbounds %struct.obj2, %struct.obj2* %o, i64 0, i32 1 133 %1 = load i32, i32* %s32, align 4 134 %dec1 = add i32 %1, -1 135 store i32 %dec1, i32* %s32, align 4 136 %tobool2 = icmp eq i32 %dec1, 0 137 br i1 %tobool2, label %if.end1, label %return 138 139; 16 bit dec 140if.end1: 141 %s16 = getelementptr inbounds %struct.obj2, %struct.obj2* %o, i64 0, i32 2 142 %2 = load i16, i16* %s16, align 2 143 %dec2 = add i16 %2, -1 144 store i16 %dec2, i16* %s16, align 2 145 %tobool3 = icmp eq i16 %dec2, 0 146 br i1 %tobool3, label %if.end2, label %return 147 148; 8 bit dec 149if.end2: 150 %s8 = getelementptr inbounds %struct.obj2, %struct.obj2* %o, i64 0, i32 3 151 %3 = load i8, i8* %s8 152 %dec3 = add i8 %3, -1 153 store i8 %dec3, i8* %s8 154 %tobool4 = icmp eq i8 %dec3, 0 155 br i1 %tobool4, label %if.end4, label %return 156 157if.end4: 158 tail call void @other(%struct.obj2* %o) nounwind 159 br label %return 160 161return: ; preds = %if.end4, %if.end, %entry 162 ret void 163} 164 165define dso_local void @example_inc(%struct.obj2* %o) nounwind uwtable ssp { 166; 64 bit inc 167; CHECK-LABEL: example_inc: 168; CHECK: # %bb.0: # %entry 169; CHECK-NEXT: incq (%rdi) 170; CHECK-NEXT: jne .LBB4_4 171; CHECK-NEXT: # %bb.1: # %if.end 172; CHECK-NEXT: incl 8(%rdi) 173; CHECK-NEXT: jne .LBB4_4 174; CHECK-NEXT: # %bb.2: # %if.end1 175; CHECK-NEXT: incw 12(%rdi) 176; CHECK-NEXT: jne .LBB4_4 177; CHECK-NEXT: # %bb.3: # %if.end2 178; CHECK-NEXT: incb 14(%rdi) 179; CHECK-NEXT: jne .LBB4_4 180; CHECK-NEXT: # %bb.5: # %if.end4 181; CHECK-NEXT: jmp other # TAILCALL 182; CHECK-NEXT: .LBB4_4: # %return 183; CHECK-NEXT: retq 184entry: 185 %s64 = getelementptr inbounds %struct.obj2, %struct.obj2* %o, i64 0, i32 0 186 %0 = load i64, i64* %s64, align 8 187 %inc = add i64 %0, 1 188 store i64 %inc, i64* %s64, align 8 189 %tobool = icmp eq i64 %inc, 0 190 br i1 %tobool, label %if.end, label %return 191 192; 32 bit inc 193if.end: 194 %s32 = getelementptr inbounds %struct.obj2, %struct.obj2* %o, i64 0, i32 1 195 %1 = load i32, i32* %s32, align 4 196 %inc1 = add i32 %1, 1 197 store i32 %inc1, i32* %s32, align 4 198 %tobool2 = icmp eq i32 %inc1, 0 199 br i1 %tobool2, label %if.end1, label %return 200 201; 16 bit inc 202if.end1: 203 %s16 = getelementptr inbounds %struct.obj2, %struct.obj2* %o, i64 0, i32 2 204 %2 = load i16, i16* %s16, align 2 205 %inc2 = add i16 %2, 1 206 store i16 %inc2, i16* %s16, align 2 207 %tobool3 = icmp eq i16 %inc2, 0 208 br i1 %tobool3, label %if.end2, label %return 209 210; 8 bit inc 211if.end2: 212 %s8 = getelementptr inbounds %struct.obj2, %struct.obj2* %o, i64 0, i32 3 213 %3 = load i8, i8* %s8 214 %inc3 = add i8 %3, 1 215 store i8 %inc3, i8* %s8 216 %tobool4 = icmp eq i8 %inc3, 0 217 br i1 %tobool4, label %if.end4, label %return 218 219if.end4: 220 tail call void @other(%struct.obj2* %o) nounwind 221 br label %return 222 223return: 224 ret void 225} 226 227; Deal with TokenFactor chain 228; rdar://11236106 229@foo = external dso_local global i64*, align 8 230 231define dso_local void @test3() nounwind ssp { 232; CHECK-LABEL: test3: 233; CHECK: # %bb.0: # %entry 234; CHECK-NEXT: movq foo(%rip), %rax 235; CHECK-NEXT: decq 16(%rax) 236; CHECK-NEXT: je .LBB5_2 237; CHECK-NEXT: # %bb.1: # %if.end 238; CHECK-NEXT: retq 239; CHECK-NEXT: .LBB5_2: # %if.then 240; CHECK-NEXT: jmp baz # TAILCALL 241entry: 242 %0 = load i64*, i64** @foo, align 8 243 %arrayidx = getelementptr inbounds i64, i64* %0, i64 2 244 %1 = load i64, i64* %arrayidx, align 8 245 %dec = add i64 %1, -1 246 store i64 %dec, i64* %arrayidx, align 8 247 %cmp = icmp eq i64 %dec, 0 248 br i1 %cmp, label %if.then, label %if.end 249 250if.then: 251 tail call void @baz() nounwind 252 br label %if.end 253 254if.end: 255 ret void 256} 257 258declare dso_local void @baz() 259 260; Avoid creating a cycle in the DAG which would trigger an assert in the 261; scheduler. 262; PR12565 263; rdar://11451474 264@x = external dso_local global i32, align 4 265@y = external dso_local global i32, align 4 266@z = external dso_local global i32, align 4 267 268define dso_local void @test4() nounwind uwtable ssp { 269; CHECK-LABEL: test4: 270; CHECK: # %bb.0: # %entry 271; CHECK-NEXT: xorl %eax, %eax 272; CHECK-NEXT: decl y(%rip) 273; CHECK-NEXT: je .LBB6_2 274; CHECK-NEXT: # %bb.1: # %entry 275; CHECK-NEXT: movl x(%rip), %eax 276; CHECK-NEXT: .LBB6_2: # %entry 277; CHECK-NEXT: movl %eax, z(%rip) 278; CHECK-NEXT: retq 279entry: 280 %0 = load i32, i32* @x, align 4 281 %1 = load i32, i32* @y, align 4 282 %dec = add nsw i32 %1, -1 283 store i32 %dec, i32* @y, align 4 284 %tobool.i = icmp ne i32 %dec, 0 285 %cond.i = select i1 %tobool.i, i32 %0, i32 0 286 store i32 %cond.i, i32* @z, align 4 287 ret void 288} 289