aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Seaborn <mseaborn@chromium.org>2013-06-12 13:24:22 -0700
committerMark Seaborn <mseaborn@chromium.org>2013-06-12 13:24:22 -0700
commit2117e90c707473abc7f2d76e5625e566c79de204 (patch)
tree9bee9c908c4d57b1dde4ed4668841fe4d40a54a0
parent062f575e014d80540f28fa7f25eab152a8ac383a (diff)
PNaCl ABI: Strip out arithmetic attributes "nsw", "nuw" and "exact"
"nsw" and "nuw" -- "no signed wrap" and "no unsigned wrap" -- are not used by the backend, which is not surprising because it makes no difference to the hardware if arithmetic overflows. Although "exact" is used by the backend to convert "sdiv exact" to an "ashr" shift, it appears that "sdiv exact" does not get used in practice, and arguably such a transformation belongs in the user toolchain, not the PNaCl translator. BUG=https://code.google.com/p/nativeclient/issues/detail?id=3483 TEST=*.ll tests + PNaCl toolchain trybots Review URL: https://codereview.chromium.org/16746005
-rw-r--r--lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp16
-rw-r--r--lib/Transforms/NaCl/StripAttributes.cpp8
-rw-r--r--test/NaCl/PNaClABI/abi-arithmetic-attributes.ll35
-rw-r--r--test/Transforms/NaCl/strip-attributes.ll11
4 files changed, 70 insertions, 0 deletions
diff --git a/lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp b/lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp
index a59f6f6682..b17fc1ab69 100644
--- a/lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp
+++ b/lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp
@@ -19,6 +19,7 @@
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Metadata.h"
+#include "llvm/IR/Operator.h"
#include "llvm/Pass.h"
#include "llvm/Support/raw_ostream.h"
@@ -322,6 +323,21 @@ const char *PNaClABIVerifyFunctions::checkInstruction(const Instruction *Inst) {
!isValidScalarOperand(Inst->getOperand(OpNum)))
return "bad operand";
}
+
+ // Check arithmetic attributes.
+ if (const OverflowingBinaryOperator *Op =
+ dyn_cast<OverflowingBinaryOperator>(Inst)) {
+ if (Op->hasNoUnsignedWrap())
+ return "has \"nuw\" attribute";
+ if (Op->hasNoSignedWrap())
+ return "has \"nsw\" attribute";
+ }
+ if (const PossiblyExactOperator *Op =
+ dyn_cast<PossiblyExactOperator>(Inst)) {
+ if (Op->isExact())
+ return "has \"exact\" attribute";
+ }
+
// Allow the instruction.
return NULL;
}
diff --git a/lib/Transforms/NaCl/StripAttributes.cpp b/lib/Transforms/NaCl/StripAttributes.cpp
index 476c500756..8074353472 100644
--- a/lib/Transforms/NaCl/StripAttributes.cpp
+++ b/lib/Transforms/NaCl/StripAttributes.cpp
@@ -22,6 +22,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/IR/Function.h"
+#include "llvm/IR/Operator.h"
#include "llvm/Pass.h"
#include "llvm/Support/CallSite.h"
#include "llvm/Transforms/NaCl.h"
@@ -144,6 +145,13 @@ bool StripAttributes::runOnFunction(Function &Func) {
CheckAttributes(Call.getAttributes());
Call.setAttributes(AttributeSet());
Call.setCallingConv(CallingConv::C);
+ } else if (OverflowingBinaryOperator *Op =
+ dyn_cast<OverflowingBinaryOperator>(Inst)) {
+ cast<BinaryOperator>(Op)->setHasNoUnsignedWrap(false);
+ cast<BinaryOperator>(Op)->setHasNoSignedWrap(false);
+ } else if (PossiblyExactOperator *Op =
+ dyn_cast<PossiblyExactOperator>(Inst)) {
+ cast<BinaryOperator>(Op)->setIsExact(false);
}
}
}
diff --git a/test/NaCl/PNaClABI/abi-arithmetic-attributes.ll b/test/NaCl/PNaClABI/abi-arithmetic-attributes.ll
new file mode 100644
index 0000000000..03304fb08c
--- /dev/null
+++ b/test/NaCl/PNaClABI/abi-arithmetic-attributes.ll
@@ -0,0 +1,35 @@
+; RUN: pnacl-abicheck < %s | FileCheck %s
+
+; This tests that the arithmetic attributes "nuw" and "nsw" ("no
+; unsigned wrap" and "no signed wrap") and "exact" are disallowed by
+; the PNaCl ABI verifier.
+
+define void @allowed_cases() {
+ %add = add i32 1, 2
+ %shl = shl i32 3, 4
+ %udiv = udiv i32 4, 2
+ %lshr = lshr i32 2, 1
+ %ashr = ashr i32 2, 1
+ ret void
+}
+; CHECK-NOT: disallowed
+
+
+define void @rejected_cases() {
+ %add = add nsw i32 1, 2
+; CHECK: disallowed: has "nsw" attribute: %add
+ %shl1 = shl nuw i32 3, 4
+; CHECK-NEXT: disallowed: has "nuw" attribute: %shl1
+ %sub = sub nsw nuw i32 5, 6
+; CHECK-NEXT: disallowed: has "nuw" attribute: %sub
+
+ %lshr = lshr exact i32 2, 1
+; CHECK-NEXT: disallowed: has "exact" attribute: %lshr
+ %ashr = ashr exact i32 2, 1
+; CHECK-NEXT: disallowed: has "exact" attribute: %ashr
+ %udiv = udiv exact i32 4, 2
+; CHECK-NEXT: disallowed: has "exact" attribute: %udiv
+
+ ret void
+}
+; CHECK-NOT: disallowed
diff --git a/test/Transforms/NaCl/strip-attributes.ll b/test/Transforms/NaCl/strip-attributes.ll
index fda8c30f6b..d4d580be81 100644
--- a/test/Transforms/NaCl/strip-attributes.ll
+++ b/test/Transforms/NaCl/strip-attributes.ll
@@ -18,3 +18,14 @@ define void @call_attrs() {
; rid of them here.
declare i8* @llvm.nacl.read.tp()
; CHECK: declare i8* @llvm.nacl.read.tp() #{{[0-9]+}}
+
+define void @arithmetic_attrs() {
+ %add = add nsw i32 1, 2
+ %shl = shl nuw i32 3, 4
+ %lshr = lshr exact i32 2, 1
+ ret void
+}
+; CHECK: define void @arithmetic_attrs() {
+; CHECK-NEXT: %add = add i32 1, 2
+; CHECK-NEXT: %shl = shl i32 3, 4
+; CHECK-NEXT: %lshr = lshr i32 2, 1