| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py |
| ; RUN: opt -S -passes=instcombine < %s | FileCheck %s |
| |
| declare void @llvm.assume(i1 noundef) |
| |
| ; Just something to let us check that separate_storage bundles don't break |
| ; anything when given an operand that's not an instruction to fold. |
| @some_global = global i32 777 |
| |
| define void @simple_folding(ptr %a, ptr %b) { |
| ; CHECK-LABEL: @simple_folding( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: call void @llvm.assume(i1 true) [ "separate_storage"(ptr [[A:%.*]], ptr [[B:%.*]]) ] |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| %p1 = getelementptr i8, ptr %a, i64 123 |
| %p2 = getelementptr i8, ptr %b, i64 777 |
| call void @llvm.assume(i1 1) ["separate_storage"(ptr %p1, ptr %p2)] |
| ret void |
| } |
| |
| define i64 @folds_removed_operands(ptr %a, ptr %b, i64 %n1, i64 %n2) { |
| ; CHECK-LABEL: @folds_removed_operands( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[REASS_ADD:%.*]] = shl i64 [[N2:%.*]], 1 |
| ; CHECK-NEXT: [[Y:%.*]] = add i64 [[REASS_ADD]], [[N1:%.*]] |
| ; CHECK-NEXT: call void @llvm.assume(i1 true) [ "separate_storage"(ptr [[A:%.*]], ptr [[B:%.*]]) ] |
| ; CHECK-NEXT: ret i64 [[Y]] |
| ; |
| entry: |
| ; Ordinarily, n1 + n2 + n2 would get canonicalized into n1 + (n2 << 1) unless |
| ; there's another use of n1 + n2. Make sure that we remember to put removed |
| ; arguments to separate_storage bundles back on the worklist. |
| %x = add i64 %n1, %n2 |
| %y = add i64 %x, %n2 |
| %p1 = getelementptr i8, ptr %a, i64 %x |
| call void @llvm.assume(i1 1) ["separate_storage"(ptr %p1, ptr %b)] |
| ret i64 %y |
| } |
| |
| define void @handles_globals(ptr %a) { |
| ; CHECK-LABEL: @handles_globals( |
| ; CHECK-NEXT: call void @llvm.assume(i1 true) [ "separate_storage"(ptr [[A:%.*]], ptr @some_global) ] |
| ; CHECK-NEXT: ret void |
| ; |
| %derived = getelementptr i8, ptr @some_global, i65 3 |
| call void @llvm.assume(i1 1) ["separate_storage"(ptr %a, ptr %derived)] |
| ret void |
| } |