| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py |
| ; RUN: opt -S -passes=gvn-hoist < %s | FileCheck %s |
| |
| ; Check that the call and fcmp are hoisted. |
| define void @fun(float %__b) minsize { |
| ; CHECK-LABEL: @fun( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[IF_THEN:%.*]] |
| ; CHECK: if.then: |
| ; CHECK-NEXT: [[TMP0:%.*]] = call float @llvm.fabs.f32(float [[__B:%.*]]) |
| ; CHECK-NEXT: [[CMPINF7:%.*]] = fcmp oeq float [[TMP0]], 0x7FF0000000000000 |
| ; CHECK-NEXT: br i1 undef, label [[IF_THEN8:%.*]], label [[LOR_LHS_FALSE:%.*]] |
| ; CHECK: lor.lhs.false: |
| ; CHECK-NEXT: unreachable |
| ; CHECK: if.then8: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %if.then |
| |
| if.then: ; preds = %entry |
| br i1 undef, label %if.then8, label %lor.lhs.false |
| |
| lor.lhs.false: ; preds = %if.then |
| %0 = call float @llvm.fabs.f32(float %__b) #2 |
| %cmpinf7 = fcmp oeq float %0, 0x7FF0000000000000 |
| unreachable |
| |
| if.then8: ; preds = %if.then |
| %1 = call float @llvm.fabs.f32(float %__b) #2 |
| %cmpinf10 = fcmp oeq float %1, 0x7FF0000000000000 |
| ret void |
| } |
| |
| declare float @llvm.fabs.f32(float) |
| |
| ; Check that extractvalues are not hoisted into entry, but that non-dependent |
| ; adds are. |
| define i32 @foo(i32 %x) { |
| ; CHECK-LABEL: @foo( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[X:%.*]], 1 |
| ; CHECK-NEXT: [[TMP0:%.*]] = callbr { i32, i32 } asm sideeffect "somestuff", "=r,=r,!i"() |
| ; CHECK-NEXT: to label [[ASM_FALLTHROUGH:%.*]] [label %err.split] |
| ; CHECK: asm.fallthrough: |
| ; CHECK-NEXT: [[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0 |
| ; CHECK-NEXT: ret i32 [[ADD]] |
| ; CHECK: err.split: |
| ; CHECK-NEXT: [[ASMRESULT2:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0 |
| ; CHECK-NEXT: ret i32 [[ADD]] |
| ; |
| entry: |
| %0 = callbr { i32, i32 } asm sideeffect "somestuff", "=r,=r,!i"() |
| to label %asm.fallthrough [label %err.split] |
| |
| asm.fallthrough: ; preds = %entry |
| %asmresult = extractvalue { i32, i32 } %0, 0 |
| %add = add nsw i32 %x, 1 |
| ret i32 %add |
| |
| err.split: ; preds = %entry |
| %asmresult2 = extractvalue { i32, i32 } %0, 0 |
| %add2 = add nsw i32 %x, 1 |
| ret i32 %add2 |
| } |
| |
| ; Check that extractvalues and dependent adds are not hoisted into entry. |
| define i32 @foo2() { |
| ; CHECK-LABEL: @foo2( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[TMP0:%.*]] = callbr { i32, i32 } asm sideeffect "somestuff", "=r,=r,!i"() |
| ; CHECK-NEXT: to label [[ASM_FALLTHROUGH:%.*]] [label %err.split] |
| ; CHECK: asm.fallthrough: |
| ; CHECK-NEXT: [[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0 |
| ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[ASMRESULT]], 1 |
| ; CHECK-NEXT: ret i32 [[ADD]] |
| ; CHECK: err.split: |
| ; CHECK-NEXT: [[ASMRESULT2:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0 |
| ; CHECK-NEXT: [[ADD2:%.*]] = add nsw i32 [[ASMRESULT2]], 1 |
| ; CHECK-NEXT: ret i32 [[ADD2]] |
| ; |
| entry: |
| %0 = callbr { i32, i32 } asm sideeffect "somestuff", "=r,=r,!i"() |
| to label %asm.fallthrough [label %err.split] |
| |
| asm.fallthrough: ; preds = %entry |
| %asmresult = extractvalue { i32, i32 } %0, 0 |
| %add = add nsw i32 %asmresult, 1 |
| ret i32 %add |
| |
| err.split: ; preds = %entry |
| %asmresult2 = extractvalue { i32, i32 } %0, 0 |
| %add2 = add nsw i32 %asmresult2, 1 |
| ret i32 %add2 |
| } |
| |
| ; Ensure we don't hoist loads that are modified by callbr. |
| @x = global i32 0 |
| define i32 @foo3() { |
| ; CHECK-LABEL: @foo3( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: callbr void asm "", "=*m,!i"(ptr elementtype(i32) @x) |
| ; CHECK-NEXT: to label [[ASM_FALLTHROUGH:%.*]] [label %err.split] |
| ; CHECK: asm.fallthrough: |
| ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr @x, align 4 |
| ; CHECK-NEXT: ret i32 [[TMP0]] |
| ; CHECK: err.split: |
| ; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr @x, align 4 |
| ; CHECK-NEXT: ret i32 [[TMP1]] |
| ; |
| entry: |
| callbr void asm "", "=*m,!i"(ptr elementtype(i32) @x) |
| to label %asm.fallthrough [label %err.split] |
| |
| asm.fallthrough: ; preds = %entry |
| %0 = load i32, ptr @x |
| ret i32 %0 |
| |
| err.split: ; preds = %entry |
| %1 = load i32, ptr @x |
| ret i32 %1 |
| } |
| |
| ; Ensure we do hoist loads that aren't modified by callbr, if the callbr has |
| ; the attribute memory(argmem:readwrite). |
| @y = global i32 0 |
| define i32 @foo4() { |
| ; CHECK-LABEL: @foo4( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr @y, align 4 |
| ; CHECK-NEXT: callbr void asm "", "=*m,!i"(ptr elementtype(i32) @x) #[[ATTR2:[0-9]+]] |
| ; CHECK-NEXT: to label [[A:%.*]] [label %b] |
| ; CHECK: a: |
| ; CHECK-NEXT: ret i32 [[TMP0]] |
| ; CHECK: b: |
| ; CHECK-NEXT: ret i32 [[TMP0]] |
| ; |
| entry: |
| callbr void asm "", "=*m,!i"(ptr elementtype(i32) @x) memory(argmem: readwrite) |
| to label %a [label %b] |
| |
| a: ; preds = %entry |
| %0 = load i32, ptr @y |
| ret i32 %0 |
| |
| b: ; preds = %entry |
| %1 = load i32, ptr @y |
| ret i32 %1 |
| } |
| |
| ; Ensure we don't hoist loads that are modified by callbr, if the callbr has |
| ; the attribute memory(argmem:readwrite). |
| define i32 @foo5() { |
| ; CHECK-LABEL: @foo5( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: callbr void asm "", "=*m,!i"(ptr elementtype(i32) @x) #[[ATTR2]] |
| ; CHECK-NEXT: to label [[A:%.*]] [label %b] |
| ; CHECK: a: |
| ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr @x, align 4 |
| ; CHECK-NEXT: ret i32 [[TMP0]] |
| ; CHECK: b: |
| ; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr @x, align 4 |
| ; CHECK-NEXT: ret i32 [[TMP1]] |
| ; |
| entry: |
| callbr void asm "", "=*m,!i"(ptr elementtype(i32) @x) memory(argmem: readwrite) |
| to label %a [label %b] |
| |
| a: ; preds = %entry |
| %0 = load i32, ptr @x |
| ret i32 %0 |
| |
| b: ; preds = %entry |
| %1 = load i32, ptr @x |
| ret i32 %1 |
| } |
| |
| ; Ensure we hoist loads that are modified by callbr, if the callbr has the |
| ; attribute memory(argmem:none). |
| define i32 @foo6() { |
| ; CHECK-LABEL: @foo6( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr @x, align 4 |
| ; CHECK-NEXT: callbr void asm "", "=*m,!i"(ptr elementtype(i32) @x) #[[ATTR3:[0-9]+]] |
| ; CHECK-NEXT: to label [[A:%.*]] [label %b] |
| ; CHECK: a: |
| ; CHECK-NEXT: ret i32 [[TMP0]] |
| ; CHECK: b: |
| ; CHECK-NEXT: ret i32 [[TMP0]] |
| ; |
| entry: |
| callbr void asm "", "=*m,!i"(ptr elementtype(i32) @x) memory(argmem: none) |
| to label %a [label %b] |
| |
| a: ; preds = %entry |
| %0 = load i32, ptr @x |
| ret i32 %0 |
| |
| b: ; preds = %entry |
| %1 = load i32, ptr @x |
| ret i32 %1 |
| } |
| |