2019-06-03 23:57:25 +08:00
|
|
|
// REQUIRES: x86-registered-target
|
|
|
|
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -O0 -emit-llvm %s -o - | FileCheck %s
|
2019-11-06 05:09:42 +08:00
|
|
|
// RUN: %clang_cc1 -triple i386-pc-linux-gnu -O0 -emit-llvm %s -o - | FileCheck %s
|
2019-06-03 23:57:25 +08:00
|
|
|
|
Support output constraints on "asm goto"
Summary:
Clang's "asm goto" feature didn't initially support outputs constraints. That
was the same behavior as gcc's implementation. The decision by gcc not to
support outputs was based on a restriction in their IR regarding terminators.
LLVM doesn't restrict terminators from returning values (e.g. 'invoke'), so
it made sense to support this feature.
Output values are valid only on the 'fallthrough' path. If an output value's used
on an indirect branch, then it's 'poisoned'.
In theory, outputs *could* be valid on the 'indirect' paths, but it's very
difficult to guarantee that the original semantics would be retained. E.g.
because indirect labels could be used as data, we wouldn't be able to split
critical edges in situations where two 'callbr' instructions have the same
indirect label, because the indirect branch's destination would no longer be
the same.
Reviewers: jyknight, nickdesaulniers, hfinkel
Reviewed By: jyknight, nickdesaulniers
Subscribers: MaskRay, rsmith, hiraditya, llvm-commits, cfe-commits, craig.topper, rnk
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D69876
2020-02-25 10:32:50 +08:00
|
|
|
int test1(int cond) {
|
|
|
|
// CHECK-LABEL: define i32 @test1(
|
2019-06-03 23:57:25 +08:00
|
|
|
// CHECK: callbr void asm sideeffect
|
2019-11-06 05:09:42 +08:00
|
|
|
// CHECK: to label %asm.fallthrough [label %label_true, label %loop]
|
Support output constraints on "asm goto"
Summary:
Clang's "asm goto" feature didn't initially support outputs constraints. That
was the same behavior as gcc's implementation. The decision by gcc not to
support outputs was based on a restriction in their IR regarding terminators.
LLVM doesn't restrict terminators from returning values (e.g. 'invoke'), so
it made sense to support this feature.
Output values are valid only on the 'fallthrough' path. If an output value's used
on an indirect branch, then it's 'poisoned'.
In theory, outputs *could* be valid on the 'indirect' paths, but it's very
difficult to guarantee that the original semantics would be retained. E.g.
because indirect labels could be used as data, we wouldn't be able to split
critical edges in situations where two 'callbr' instructions have the same
indirect label, because the indirect branch's destination would no longer be
the same.
Reviewers: jyknight, nickdesaulniers, hfinkel
Reviewed By: jyknight, nickdesaulniers
Subscribers: MaskRay, rsmith, hiraditya, llvm-commits, cfe-commits, craig.topper, rnk
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D69876
2020-02-25 10:32:50 +08:00
|
|
|
// CHECK-LABEL: asm.fallthrough:
|
2019-06-03 23:57:25 +08:00
|
|
|
asm volatile goto("testl %0, %0; jne %l1;" :: "r"(cond)::label_true, loop);
|
Support output constraints on "asm goto"
Summary:
Clang's "asm goto" feature didn't initially support outputs constraints. That
was the same behavior as gcc's implementation. The decision by gcc not to
support outputs was based on a restriction in their IR regarding terminators.
LLVM doesn't restrict terminators from returning values (e.g. 'invoke'), so
it made sense to support this feature.
Output values are valid only on the 'fallthrough' path. If an output value's used
on an indirect branch, then it's 'poisoned'.
In theory, outputs *could* be valid on the 'indirect' paths, but it's very
difficult to guarantee that the original semantics would be retained. E.g.
because indirect labels could be used as data, we wouldn't be able to split
critical edges in situations where two 'callbr' instructions have the same
indirect label, because the indirect branch's destination would no longer be
the same.
Reviewers: jyknight, nickdesaulniers, hfinkel
Reviewed By: jyknight, nickdesaulniers
Subscribers: MaskRay, rsmith, hiraditya, llvm-commits, cfe-commits, craig.topper, rnk
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D69876
2020-02-25 10:32:50 +08:00
|
|
|
asm volatile goto("testl %0, %0; jne %l2;" :: "r"(cond)::label_true, loop);
|
2019-06-03 23:57:25 +08:00
|
|
|
// CHECK: callbr void asm sideeffect
|
2019-11-06 05:09:42 +08:00
|
|
|
// CHECK: to label %asm.fallthrough1 [label %label_true, label %loop]
|
Support output constraints on "asm goto"
Summary:
Clang's "asm goto" feature didn't initially support outputs constraints. That
was the same behavior as gcc's implementation. The decision by gcc not to
support outputs was based on a restriction in their IR regarding terminators.
LLVM doesn't restrict terminators from returning values (e.g. 'invoke'), so
it made sense to support this feature.
Output values are valid only on the 'fallthrough' path. If an output value's used
on an indirect branch, then it's 'poisoned'.
In theory, outputs *could* be valid on the 'indirect' paths, but it's very
difficult to guarantee that the original semantics would be retained. E.g.
because indirect labels could be used as data, we wouldn't be able to split
critical edges in situations where two 'callbr' instructions have the same
indirect label, because the indirect branch's destination would no longer be
the same.
Reviewers: jyknight, nickdesaulniers, hfinkel
Reviewed By: jyknight, nickdesaulniers
Subscribers: MaskRay, rsmith, hiraditya, llvm-commits, cfe-commits, craig.topper, rnk
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D69876
2020-02-25 10:32:50 +08:00
|
|
|
// CHECK-LABEL: asm.fallthrough1:
|
|
|
|
return 0;
|
|
|
|
loop:
|
|
|
|
return 0;
|
|
|
|
label_true:
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int test2(int cond) {
|
|
|
|
// CHECK-LABEL: define i32 @test2(
|
|
|
|
// CHECK: callbr i32 asm sideeffect
|
|
|
|
// CHECK: to label %asm.fallthrough [label %label_true, label %loop]
|
|
|
|
// CHECK-LABEL: asm.fallthrough:
|
|
|
|
asm volatile goto("testl %0, %0; jne %l2;" : "=r"(cond) : "r"(cond) :: label_true, loop);
|
|
|
|
asm volatile goto("testl %0, %0; jne %l3;" : "=r"(cond) : "r"(cond) :: label_true, loop);
|
|
|
|
// CHECK: callbr i32 asm sideeffect
|
|
|
|
// CHECK: to label %asm.fallthrough1 [label %label_true, label %loop]
|
|
|
|
// CHECK-LABEL: asm.fallthrough1:
|
|
|
|
return 0;
|
|
|
|
loop:
|
|
|
|
return 0;
|
|
|
|
label_true:
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int test3(int out1, int out2) {
|
|
|
|
// CHECK-LABEL: define i32 @test3(
|
|
|
|
// CHECK: callbr { i32, i32 } asm sideeffect
|
|
|
|
// CHECK: to label %asm.fallthrough [label %label_true, label %loop]
|
|
|
|
// CHECK-LABEL: asm.fallthrough:
|
|
|
|
asm volatile goto("testl %0, %0; jne %l3;" : "=r"(out1), "=r"(out2) : "r"(out1) :: label_true, loop);
|
|
|
|
asm volatile goto("testl %0, %0; jne %l4;" : "=r"(out1), "=r"(out2) : "r"(out1) :: label_true, loop);
|
|
|
|
// CHECK: callbr { i32, i32 } asm sideeffect
|
|
|
|
// CHECK: to label %asm.fallthrough2 [label %label_true, label %loop]
|
|
|
|
// CHECK-LABEL: asm.fallthrough2:
|
2019-06-03 23:57:25 +08:00
|
|
|
return 0;
|
|
|
|
loop:
|
|
|
|
return 0;
|
|
|
|
label_true:
|
|
|
|
return 1;
|
|
|
|
}
|
Support output constraints on "asm goto"
Summary:
Clang's "asm goto" feature didn't initially support outputs constraints. That
was the same behavior as gcc's implementation. The decision by gcc not to
support outputs was based on a restriction in their IR regarding terminators.
LLVM doesn't restrict terminators from returning values (e.g. 'invoke'), so
it made sense to support this feature.
Output values are valid only on the 'fallthrough' path. If an output value's used
on an indirect branch, then it's 'poisoned'.
In theory, outputs *could* be valid on the 'indirect' paths, but it's very
difficult to guarantee that the original semantics would be retained. E.g.
because indirect labels could be used as data, we wouldn't be able to split
critical edges in situations where two 'callbr' instructions have the same
indirect label, because the indirect branch's destination would no longer be
the same.
Reviewers: jyknight, nickdesaulniers, hfinkel
Reviewed By: jyknight, nickdesaulniers
Subscribers: MaskRay, rsmith, hiraditya, llvm-commits, cfe-commits, craig.topper, rnk
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D69876
2020-02-25 10:32:50 +08:00
|
|
|
|
|
|
|
int test4(int out1, int out2) {
|
|
|
|
// CHECK-LABEL: define i32 @test4(
|
|
|
|
// CHECK: callbr { i32, i32 } asm sideeffect "jne ${3:l}", "={si},={di},r,X,X,0,1
|
|
|
|
// CHECK: to label %asm.fallthrough [label %label_true, label %loop]
|
|
|
|
// CHECK-LABEL: asm.fallthrough:
|
|
|
|
if (out1 < out2)
|
|
|
|
asm volatile goto("jne %l3" : "+S"(out1), "+D"(out2) : "r"(out1) :: label_true, loop);
|
|
|
|
else
|
|
|
|
asm volatile goto("jne %l5" : "+S"(out1), "+D"(out2) : "r"(out1), "r"(out2) :: label_true, loop);
|
|
|
|
// CHECK: callbr { i32, i32 } asm sideeffect "jne ${5:l}", "={si},={di},r,r,X,X,0,1
|
|
|
|
// CHECK: to label %asm.fallthrough2 [label %label_true, label %loop]
|
|
|
|
// CHECK-LABEL: asm.fallthrough2:
|
|
|
|
return out1 + out2;
|
|
|
|
loop:
|
|
|
|
return -1;
|
|
|
|
label_true:
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
|
|
|
|
int test5(int addr, int size, int limit) {
|
|
|
|
// CHECK-LABEL: define i32 @test5(
|
|
|
|
// CHECK: callbr i32 asm "add $1,$0 ; jc ${3:l} ; cmp $2,$0 ; ja ${3:l} ; ", "=r,imr,imr,X,0
|
|
|
|
// CHECK: to label %asm.fallthrough [label %t_err]
|
|
|
|
// CHECK-LABEL: asm.fallthrough:
|
|
|
|
asm goto(
|
|
|
|
"add %1,%0 ; "
|
|
|
|
"jc %l[t_err] ; "
|
|
|
|
"cmp %2,%0 ; "
|
|
|
|
"ja %l[t_err] ; "
|
|
|
|
: "+r" (addr)
|
|
|
|
: "g" (size), "g" (limit)
|
|
|
|
: : t_err);
|
|
|
|
return 0;
|
|
|
|
t_err:
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int test6(int out1) {
|
|
|
|
// CHECK-LABEL: define i32 @test6(
|
|
|
|
// CHECK: callbr i32 asm sideeffect "testl $0, $0; testl $1, $1; jne ${2:l}", "={si},r,X,X,0,{{.*}} i8* blockaddress(@test6, %label_true), i8* blockaddress(@test6, %landing)
|
|
|
|
// CHECK: to label %asm.fallthrough [label %label_true, label %landing]
|
|
|
|
// CHECK-LABEL: asm.fallthrough:
|
|
|
|
// CHECK-LABEL: landing:
|
|
|
|
int out2 = 42;
|
|
|
|
asm volatile goto("testl %0, %0; testl %1, %1; jne %l2" : "+S"(out2) : "r"(out1) :: label_true, landing);
|
|
|
|
landing:
|
|
|
|
return out1 + out2;
|
|
|
|
label_true:
|
|
|
|
return -2;
|
|
|
|
}
|