brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.3 KiB · 12df378 Raw
196 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s3 4; The fundamental problem: an add separated from other arithmetic by a sign or5; zero extension can't be combined with the later instructions. However, if the6; first add is 'nsw' or 'nuw' respectively, then we can promote the extension7; ahead of that add to allow optimizations.8 9define i64 @add_nsw_consts(i32 %i) {10; CHECK-LABEL: add_nsw_consts:11; CHECK:       # %bb.0:12; CHECK-NEXT:    movslq %edi, %rax13; CHECK-NEXT:    addq $12, %rax14; CHECK-NEXT:    retq15 16  %add = add nsw i32 %i, 517  %ext = sext i32 %add to i6418  %idx = add i64 %ext, 719  ret i64 %idx20}21 22; An x86 bonus: If we promote the sext ahead of the 'add nsw',23; we allow LEA formation and eliminate an add instruction.24 25define i64 @add_nsw_sext_add(i32 %i, i64 %x) {26; CHECK-LABEL: add_nsw_sext_add:27; CHECK:       # %bb.0:28; CHECK-NEXT:    movslq %edi, %rax29; CHECK-NEXT:    leaq 5(%rax,%rsi), %rax30; CHECK-NEXT:    retq31 32  %add = add nsw i32 %i, 533  %ext = sext i32 %add to i6434  %idx = add i64 %x, %ext35  ret i64 %idx36}37 38; Throw in a scale (left shift) because an LEA can do that too.39; Use a negative constant (LEA displacement) to verify that's handled correctly.40 41define i64 @add_nsw_sext_lsh_add(i32 %i, i64 %x) {42; CHECK-LABEL: add_nsw_sext_lsh_add:43; CHECK:       # %bb.0:44; CHECK-NEXT:    movslq %edi, %rax45; CHECK-NEXT:    leaq -40(%rsi,%rax,8), %rax46; CHECK-NEXT:    retq47 48  %add = add nsw i32 %i, -549  %ext = sext i32 %add to i6450  %shl = shl i64 %ext, 351  %idx = add i64 %x, %shl52  ret i64 %idx53}54 55; Don't promote the sext if it has no users. The wider add instruction needs an56; extra byte to encode.57 58define i64 @add_nsw_sext(i32 %i, i64 %x) {59; CHECK-LABEL: add_nsw_sext:60; CHECK:       # %bb.0:61; CHECK-NEXT:    addl $5, %edi62; CHECK-NEXT:    movslq %edi, %rax63; CHECK-NEXT:    retq64 65  %add = add nsw i32 %i, 566  %ext = sext i32 %add to i6467  ret i64 %ext68}69 70; The typical use case: a 64-bit system where an 'int' is used as an index into an array.71 72define ptr @gep8(i32 %i, ptr %x) {73; CHECK-LABEL: gep8:74; CHECK:       # %bb.0:75; CHECK-NEXT:    movslq %edi, %rax76; CHECK-NEXT:    leaq 5(%rax,%rsi), %rax77; CHECK-NEXT:    retq78 79  %add = add nsw i32 %i, 580  %ext = sext i32 %add to i6481  %idx = getelementptr i8, ptr %x, i64 %ext82  ret ptr %idx83}84 85define ptr @gep16(i32 %i, ptr %x) {86; CHECK-LABEL: gep16:87; CHECK:       # %bb.0:88; CHECK-NEXT:    movslq %edi, %rax89; CHECK-NEXT:    leaq -10(%rsi,%rax,2), %rax90; CHECK-NEXT:    retq91 92  %add = add nsw i32 %i, -593  %ext = sext i32 %add to i6494  %idx = getelementptr i16, ptr %x, i64 %ext95  ret ptr %idx96}97 98define ptr @gep32(i32 %i, ptr %x) {99; CHECK-LABEL: gep32:100; CHECK:       # %bb.0:101; CHECK-NEXT:    movslq %edi, %rax102; CHECK-NEXT:    leaq 20(%rsi,%rax,4), %rax103; CHECK-NEXT:    retq104 105  %add = add nsw i32 %i, 5106  %ext = sext i32 %add to i64107  %idx = getelementptr i32, ptr %x, i64 %ext108  ret ptr %idx109}110 111define ptr @gep64(i32 %i, ptr %x) {112; CHECK-LABEL: gep64:113; CHECK:       # %bb.0:114; CHECK-NEXT:    movslq %edi, %rax115; CHECK-NEXT:    leaq -40(%rsi,%rax,8), %rax116; CHECK-NEXT:    retq117 118  %add = add nsw i32 %i, -5119  %ext = sext i32 %add to i64120  %idx = getelementptr i64, ptr %x, i64 %ext121  ret ptr %idx122}123 124; LEA can't scale by 16, but the adds can still be combined into an LEA.125 126define ptr @gep128(i32 %i, ptr %x) {127; CHECK-LABEL: gep128:128; CHECK:       # %bb.0:129; CHECK-NEXT:    movslq %edi, %rax130; CHECK-NEXT:    shlq $4, %rax131; CHECK-NEXT:    leaq 80(%rax,%rsi), %rax132; CHECK-NEXT:    retq133 134  %add = add nsw i32 %i, 5135  %ext = sext i32 %add to i64136  %idx = getelementptr i128, ptr %x, i64 %ext137  ret ptr %idx138}139 140; A bigger win can be achieved when there is more than one use of the141; sign extended value. In this case, we can eliminate sign extension142; instructions plus use more efficient addressing modes for memory ops.143 144define void @PR20134(ptr %a, i32 %i) {145; CHECK-LABEL: PR20134:146; CHECK:       # %bb.0:147; CHECK-NEXT:    movslq %esi, %rax148; CHECK-NEXT:    movl 4(%rdi,%rax,4), %ecx149; CHECK-NEXT:    addl 8(%rdi,%rax,4), %ecx150; CHECK-NEXT:    movl %ecx, (%rdi,%rax,4)151; CHECK-NEXT:    retq152 153  %add1 = add nsw i32 %i, 1154  %idx1 = sext i32 %add1 to i64155  %gep1 = getelementptr i32, ptr %a, i64 %idx1156  %load1 = load i32, ptr %gep1, align 4157 158  %add2 = add nsw i32 %i, 2159  %idx2 = sext i32 %add2 to i64160  %gep2 = getelementptr i32, ptr %a, i64 %idx2161  %load2 = load i32, ptr %gep2, align 4162 163  %add3 = add i32 %load1, %load2164  %idx3 = sext i32 %i to i64165  %gep3 = getelementptr i32, ptr %a, i64 %idx3166  store i32 %add3, ptr %gep3, align 4167  ret void168}169 170; The same as @PR20134 but sign extension is replaced with zero extension171define void @PR20134_zext(ptr %a, i32 %i) {172; CHECK-LABEL: PR20134_zext:173; CHECK:       # %bb.0:174; CHECK-NEXT:    movl %esi, %eax175; CHECK-NEXT:    movl 4(%rdi,%rax,4), %ecx176; CHECK-NEXT:    addl 8(%rdi,%rax,4), %ecx177; CHECK-NEXT:    movl %ecx, (%rdi,%rax,4)178; CHECK-NEXT:    retq179 180  %add1 = add nuw i32 %i, 1181  %idx1 = zext i32 %add1 to i64182  %gep1 = getelementptr i32, ptr %a, i64 %idx1183  %load1 = load i32, ptr %gep1, align 4184 185  %add2 = add nuw i32 %i, 2186  %idx2 = zext i32 %add2 to i64187  %gep2 = getelementptr i32, ptr %a, i64 %idx2188  %load2 = load i32, ptr %gep2, align 4189 190  %add3 = add i32 %load1, %load2191  %idx3 = zext i32 %i to i64192  %gep3 = getelementptr i32, ptr %a, i64 %idx3193  store i32 %add3, ptr %gep3, align 4194  ret void195}196