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