diff options
author | Mark Seaborn <mseaborn@chromium.org> | 2013-06-12 13:24:22 -0700 |
---|---|---|
committer | Mark Seaborn <mseaborn@chromium.org> | 2013-06-12 13:24:22 -0700 |
commit | 2117e90c707473abc7f2d76e5625e566c79de204 (patch) | |
tree | 9bee9c908c4d57b1dde4ed4668841fe4d40a54a0 | |
parent | 062f575e014d80540f28fa7f25eab152a8ac383a (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.cpp | 16 | ||||
-rw-r--r-- | lib/Transforms/NaCl/StripAttributes.cpp | 8 | ||||
-rw-r--r-- | test/NaCl/PNaClABI/abi-arithmetic-attributes.ll | 35 | ||||
-rw-r--r-- | test/Transforms/NaCl/strip-attributes.ll | 11 |
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 |