1*9880d681SAndroid Build Coastguard Worker; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2*9880d681SAndroid Build Coastguard Worker; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s 3*9880d681SAndroid Build Coastguard Worker 4*9880d681SAndroid Build Coastguard Worker; The fundamental problem: an add separated from other arithmetic by a sext can't 5*9880d681SAndroid Build Coastguard Worker; be combined with the later instructions. However, if the first add is 'nsw', 6*9880d681SAndroid Build Coastguard Worker; then we can promote the sext ahead of that add to allow optimizations. 7*9880d681SAndroid Build Coastguard Worker 8*9880d681SAndroid Build Coastguard Workerdefine i64 @add_nsw_consts(i32 %i) { 9*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: add_nsw_consts: 10*9880d681SAndroid Build Coastguard Worker; CHECK: # BB#0: 11*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: movslq %edi, %rax 12*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: addq $12, %rax 13*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: retq 14*9880d681SAndroid Build Coastguard Worker 15*9880d681SAndroid Build Coastguard Worker %add = add nsw i32 %i, 5 16*9880d681SAndroid Build Coastguard Worker %ext = sext i32 %add to i64 17*9880d681SAndroid Build Coastguard Worker %idx = add i64 %ext, 7 18*9880d681SAndroid Build Coastguard Worker ret i64 %idx 19*9880d681SAndroid Build Coastguard Worker} 20*9880d681SAndroid Build Coastguard Worker 21*9880d681SAndroid Build Coastguard Worker; An x86 bonus: If we promote the sext ahead of the 'add nsw', 22*9880d681SAndroid Build Coastguard Worker; we allow LEA formation and eliminate an add instruction. 23*9880d681SAndroid Build Coastguard Worker 24*9880d681SAndroid Build Coastguard Workerdefine i64 @add_nsw_sext_add(i32 %i, i64 %x) { 25*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: add_nsw_sext_add: 26*9880d681SAndroid Build Coastguard Worker; CHECK: # BB#0: 27*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: movslq %edi, %rax 28*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: leaq 5(%rsi,%rax), %rax 29*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: retq 30*9880d681SAndroid Build Coastguard Worker 31*9880d681SAndroid Build Coastguard Worker %add = add nsw i32 %i, 5 32*9880d681SAndroid Build Coastguard Worker %ext = sext i32 %add to i64 33*9880d681SAndroid Build Coastguard Worker %idx = add i64 %x, %ext 34*9880d681SAndroid Build Coastguard Worker ret i64 %idx 35*9880d681SAndroid Build Coastguard Worker} 36*9880d681SAndroid Build Coastguard Worker 37*9880d681SAndroid Build Coastguard Worker; Throw in a scale (left shift) because an LEA can do that too. 38*9880d681SAndroid Build Coastguard Worker; Use a negative constant (LEA displacement) to verify that's handled correctly. 39*9880d681SAndroid Build Coastguard Worker 40*9880d681SAndroid Build Coastguard Workerdefine i64 @add_nsw_sext_lsh_add(i32 %i, i64 %x) { 41*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: add_nsw_sext_lsh_add: 42*9880d681SAndroid Build Coastguard Worker; CHECK: # BB#0: 43*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: movslq %edi, %rax 44*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: leaq -40(%rsi,%rax,8), %rax 45*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: retq 46*9880d681SAndroid Build Coastguard Worker 47*9880d681SAndroid Build Coastguard Worker %add = add nsw i32 %i, -5 48*9880d681SAndroid Build Coastguard Worker %ext = sext i32 %add to i64 49*9880d681SAndroid Build Coastguard Worker %shl = shl i64 %ext, 3 50*9880d681SAndroid Build Coastguard Worker %idx = add i64 %x, %shl 51*9880d681SAndroid Build Coastguard Worker ret i64 %idx 52*9880d681SAndroid Build Coastguard Worker} 53*9880d681SAndroid Build Coastguard Worker 54*9880d681SAndroid Build Coastguard Worker; Don't promote the sext if it has no users. The wider add instruction needs an 55*9880d681SAndroid Build Coastguard Worker; extra byte to encode. 56*9880d681SAndroid Build Coastguard Worker 57*9880d681SAndroid Build Coastguard Workerdefine i64 @add_nsw_sext(i32 %i, i64 %x) { 58*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: add_nsw_sext: 59*9880d681SAndroid Build Coastguard Worker; CHECK: # BB#0: 60*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: addl $5, %edi 61*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: movslq %edi, %rax 62*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: retq 63*9880d681SAndroid Build Coastguard Worker 64*9880d681SAndroid Build Coastguard Worker %add = add nsw i32 %i, 5 65*9880d681SAndroid Build Coastguard Worker %ext = sext i32 %add to i64 66*9880d681SAndroid Build Coastguard Worker ret i64 %ext 67*9880d681SAndroid Build Coastguard Worker} 68*9880d681SAndroid Build Coastguard Worker 69*9880d681SAndroid Build Coastguard Worker; The typical use case: a 64-bit system where an 'int' is used as an index into an array. 70*9880d681SAndroid Build Coastguard Worker 71*9880d681SAndroid Build Coastguard Workerdefine i8* @gep8(i32 %i, i8* %x) { 72*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: gep8: 73*9880d681SAndroid Build Coastguard Worker; CHECK: # BB#0: 74*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: movslq %edi, %rax 75*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: leaq 5(%rsi,%rax), %rax 76*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: retq 77*9880d681SAndroid Build Coastguard Worker 78*9880d681SAndroid Build Coastguard Worker %add = add nsw i32 %i, 5 79*9880d681SAndroid Build Coastguard Worker %ext = sext i32 %add to i64 80*9880d681SAndroid Build Coastguard Worker %idx = getelementptr i8, i8* %x, i64 %ext 81*9880d681SAndroid Build Coastguard Worker ret i8* %idx 82*9880d681SAndroid Build Coastguard Worker} 83*9880d681SAndroid Build Coastguard Worker 84*9880d681SAndroid Build Coastguard Workerdefine i16* @gep16(i32 %i, i16* %x) { 85*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: gep16: 86*9880d681SAndroid Build Coastguard Worker; CHECK: # BB#0: 87*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: movslq %edi, %rax 88*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: leaq -10(%rsi,%rax,2), %rax 89*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: retq 90*9880d681SAndroid Build Coastguard Worker 91*9880d681SAndroid Build Coastguard Worker %add = add nsw i32 %i, -5 92*9880d681SAndroid Build Coastguard Worker %ext = sext i32 %add to i64 93*9880d681SAndroid Build Coastguard Worker %idx = getelementptr i16, i16* %x, i64 %ext 94*9880d681SAndroid Build Coastguard Worker ret i16* %idx 95*9880d681SAndroid Build Coastguard Worker} 96*9880d681SAndroid Build Coastguard Worker 97*9880d681SAndroid Build Coastguard Workerdefine i32* @gep32(i32 %i, i32* %x) { 98*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: gep32: 99*9880d681SAndroid Build Coastguard Worker; CHECK: # BB#0: 100*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: movslq %edi, %rax 101*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: leaq 20(%rsi,%rax,4), %rax 102*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: retq 103*9880d681SAndroid Build Coastguard Worker 104*9880d681SAndroid Build Coastguard Worker %add = add nsw i32 %i, 5 105*9880d681SAndroid Build Coastguard Worker %ext = sext i32 %add to i64 106*9880d681SAndroid Build Coastguard Worker %idx = getelementptr i32, i32* %x, i64 %ext 107*9880d681SAndroid Build Coastguard Worker ret i32* %idx 108*9880d681SAndroid Build Coastguard Worker} 109*9880d681SAndroid Build Coastguard Worker 110*9880d681SAndroid Build Coastguard Workerdefine i64* @gep64(i32 %i, i64* %x) { 111*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: gep64: 112*9880d681SAndroid Build Coastguard Worker; CHECK: # BB#0: 113*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: movslq %edi, %rax 114*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: leaq -40(%rsi,%rax,8), %rax 115*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: retq 116*9880d681SAndroid Build Coastguard Worker 117*9880d681SAndroid Build Coastguard Worker %add = add nsw i32 %i, -5 118*9880d681SAndroid Build Coastguard Worker %ext = sext i32 %add to i64 119*9880d681SAndroid Build Coastguard Worker %idx = getelementptr i64, i64* %x, i64 %ext 120*9880d681SAndroid Build Coastguard Worker ret i64* %idx 121*9880d681SAndroid Build Coastguard Worker} 122*9880d681SAndroid Build Coastguard Worker 123*9880d681SAndroid Build Coastguard Worker; LEA can't scale by 16, but the adds can still be combined into an LEA. 124*9880d681SAndroid Build Coastguard Worker 125*9880d681SAndroid Build Coastguard Workerdefine i128* @gep128(i32 %i, i128* %x) { 126*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: gep128: 127*9880d681SAndroid Build Coastguard Worker; CHECK: # BB#0: 128*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: movslq %edi, %rax 129*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: shlq $4, %rax 130*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: leaq 80(%rsi,%rax), %rax 131*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: retq 132*9880d681SAndroid Build Coastguard Worker 133*9880d681SAndroid Build Coastguard Worker %add = add nsw i32 %i, 5 134*9880d681SAndroid Build Coastguard Worker %ext = sext i32 %add to i64 135*9880d681SAndroid Build Coastguard Worker %idx = getelementptr i128, i128* %x, i64 %ext 136*9880d681SAndroid Build Coastguard Worker ret i128* %idx 137*9880d681SAndroid Build Coastguard Worker} 138*9880d681SAndroid Build Coastguard Worker 139*9880d681SAndroid Build Coastguard Worker; A bigger win can be achieved when there is more than one use of the 140*9880d681SAndroid Build Coastguard Worker; sign extended value. In this case, we can eliminate sign extension 141*9880d681SAndroid Build Coastguard Worker; instructions plus use more efficient addressing modes for memory ops. 142*9880d681SAndroid Build Coastguard Worker 143*9880d681SAndroid Build Coastguard Workerdefine void @PR20134(i32* %a, i32 %i) { 144*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: PR20134: 145*9880d681SAndroid Build Coastguard Worker; CHECK: # BB#0: 146*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: movslq %esi, %rax 147*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: movl 4(%rdi,%rax,4), %ecx 148*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: addl 8(%rdi,%rax,4), %ecx 149*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: movl %ecx, (%rdi,%rax,4) 150*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: retq 151*9880d681SAndroid Build Coastguard Worker 152*9880d681SAndroid Build Coastguard Worker %add1 = add nsw i32 %i, 1 153*9880d681SAndroid Build Coastguard Worker %idx1 = sext i32 %add1 to i64 154*9880d681SAndroid Build Coastguard Worker %gep1 = getelementptr i32, i32* %a, i64 %idx1 155*9880d681SAndroid Build Coastguard Worker %load1 = load i32, i32* %gep1, align 4 156*9880d681SAndroid Build Coastguard Worker 157*9880d681SAndroid Build Coastguard Worker %add2 = add nsw i32 %i, 2 158*9880d681SAndroid Build Coastguard Worker %idx2 = sext i32 %add2 to i64 159*9880d681SAndroid Build Coastguard Worker %gep2 = getelementptr i32, i32* %a, i64 %idx2 160*9880d681SAndroid Build Coastguard Worker %load2 = load i32, i32* %gep2, align 4 161*9880d681SAndroid Build Coastguard Worker 162*9880d681SAndroid Build Coastguard Worker %add3 = add i32 %load1, %load2 163*9880d681SAndroid Build Coastguard Worker %idx3 = sext i32 %i to i64 164*9880d681SAndroid Build Coastguard Worker %gep3 = getelementptr i32, i32* %a, i64 %idx3 165*9880d681SAndroid Build Coastguard Worker store i32 %add3, i32* %gep3, align 4 166*9880d681SAndroid Build Coastguard Worker ret void 167*9880d681SAndroid Build Coastguard Worker} 168*9880d681SAndroid Build Coastguard Worker 169