diff options
author | Dan Gohman <gohman@apple.com> | 2009-07-20 21:19:07 +0000 |
---|---|---|
committer | Dan Gohman <gohman@apple.com> | 2009-07-20 21:19:07 +0000 |
commit | 1224c386981f7948f298ed9ad444c40609570f2e (patch) | |
tree | 69577cb79bc2b30c8f801de5c52a374189fdb7a4 | |
parent | 33d0474bf5d5783cf9690bcab3eabd513d918fc5 (diff) |
Assembly and Bitcode support for unsigned/signed overflow flags and
exact sdiv flags.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@76475 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/llvm/Bitcode/LLVMBitCodes.h | 12 | ||||
-rw-r--r-- | lib/AsmParser/LLLexer.cpp | 3 | ||||
-rw-r--r-- | lib/AsmParser/LLParser.cpp | 88 | ||||
-rw-r--r-- | lib/AsmParser/LLToken.h | 3 | ||||
-rw-r--r-- | lib/Bitcode/Reader/BitcodeReader.cpp | 27 | ||||
-rw-r--r-- | lib/Bitcode/Writer/BitcodeWriter.cpp | 38 | ||||
-rw-r--r-- | lib/VMCore/AsmWriter.cpp | 18 | ||||
-rw-r--r-- | test/Assembler/flags-plain.ll | 23 | ||||
-rw-r--r-- | test/Assembler/flags-reversed.ll | 18 | ||||
-rw-r--r-- | test/Assembler/flags-signed.ll | 18 | ||||
-rw-r--r-- | test/Assembler/flags-unsigned.ll | 18 | ||||
-rw-r--r-- | test/Assembler/flags.ll | 125 |
12 files changed, 387 insertions, 4 deletions
diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h index c3a1bc1d8a..753d0ff44c 100644 --- a/include/llvm/Bitcode/LLVMBitCodes.h +++ b/include/llvm/Bitcode/LLVMBitCodes.h @@ -171,6 +171,18 @@ namespace bitc { BINOP_XOR = 12 }; + /// OverflowingBinaryOperatorOptionalFlags - Flags for serializing + /// OverflowingBinaryOperator's SubclassOptionalData contents. + enum OverflowingBinaryOperatorOptionalFlags { + OBO_NO_UNSIGNED_OVERFLOW = 0, + OBO_NO_SIGNED_OVERFLOW = 1 + }; + + /// SDivOperatorOptionalFlags - Flags for serializing SDivOperator's + /// SubclassOptionalData contents. + enum SDivOperatorOptionalFlags { + SDIV_EXACT = 0 + }; // The function body block (FUNCTION_BLOCK_ID) describes function bodies. It // can contain a constant block (CONSTANTS_BLOCK_ID). diff --git a/lib/AsmParser/LLLexer.cpp b/lib/AsmParser/LLLexer.cpp index a2e5b76fd3..313213cb48 100644 --- a/lib/AsmParser/LLLexer.cpp +++ b/lib/AsmParser/LLLexer.cpp @@ -501,6 +501,9 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(deplibs); KEYWORD(datalayout); KEYWORD(volatile); + KEYWORD(signed); + KEYWORD(unsigned); + KEYWORD(exact); KEYWORD(align); KEYWORD(addrspace); KEYWORD(section); diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index c0b74a2e4c..cbed8695bf 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -21,6 +21,7 @@ #include "llvm/LLVMContext.h" #include "llvm/MDNode.h" #include "llvm/Module.h" +#include "llvm/Operator.h" #include "llvm/ValueSymbolTable.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringExtras.h" @@ -2041,6 +2042,49 @@ bool LLParser::ParseValID(ValID &ID) { ID.Kind = ValID::t_Constant; return false; } + case lltok::kw_signed: { + Lex.Lex(); + bool AlsoUnsigned = EatIfPresent(lltok::kw_unsigned); + if (Lex.getKind() != lltok::kw_add && + Lex.getKind() != lltok::kw_sub && + Lex.getKind() != lltok::kw_mul) + return TokError("expected 'add', 'sub', or 'mul'"); + bool Result = LLParser::ParseValID(ID); + if (!Result) { + cast<OverflowingBinaryOperator>(ID.ConstantVal) + ->setHasNoSignedOverflow(true); + if (AlsoUnsigned) + cast<OverflowingBinaryOperator>(ID.ConstantVal) + ->setHasNoUnsignedOverflow(true); + } + return Result; + } + case lltok::kw_unsigned: { + Lex.Lex(); + bool AlsoSigned = EatIfPresent(lltok::kw_signed); + if (Lex.getKind() != lltok::kw_add && + Lex.getKind() != lltok::kw_sub && + Lex.getKind() != lltok::kw_mul) + return TokError("expected 'add', 'sub', or 'mul'"); + bool Result = LLParser::ParseValID(ID); + if (!Result) { + cast<OverflowingBinaryOperator>(ID.ConstantVal) + ->setHasNoUnsignedOverflow(true); + if (AlsoSigned) + cast<OverflowingBinaryOperator>(ID.ConstantVal) + ->setHasNoSignedOverflow(true); + } + return Result; + } + case lltok::kw_exact: { + Lex.Lex(); + if (Lex.getKind() != lltok::kw_sdiv) + return TokError("expected 'sdiv'"); + bool Result = LLParser::ParseValID(ID); + if (!Result) + cast<SDivOperator>(ID.ConstantVal)->setIsExact(true); + return Result; + } } Lex.Lex(); @@ -2558,6 +2602,50 @@ bool LLParser::ParseInstruction(Instruction *&Inst, BasicBlock *BB, return ParseStore(Inst, PFS, true); else return TokError("expected 'load' or 'store'"); + case lltok::kw_signed: { + bool AlsoUnsigned = EatIfPresent(lltok::kw_unsigned); + if (Lex.getKind() == lltok::kw_add || + Lex.getKind() == lltok::kw_sub || + Lex.getKind() == lltok::kw_mul) { + Lex.Lex(); + KeywordVal = Lex.getUIntVal(); + bool Result = ParseArithmetic(Inst, PFS, KeywordVal, 0); + if (!Result) { + cast<OverflowingBinaryOperator>(Inst)->setHasNoSignedOverflow(true); + if (AlsoUnsigned) + cast<OverflowingBinaryOperator>(Inst)->setHasNoUnsignedOverflow(true); + } + return Result; + } + return TokError("expected 'add', 'sub', or 'mul'"); + } + case lltok::kw_unsigned: { + bool AlsoSigned = EatIfPresent(lltok::kw_signed); + if (Lex.getKind() == lltok::kw_add || + Lex.getKind() == lltok::kw_sub || + Lex.getKind() == lltok::kw_mul) { + Lex.Lex(); + KeywordVal = Lex.getUIntVal(); + bool Result = ParseArithmetic(Inst, PFS, KeywordVal, 1); + if (!Result) { + cast<OverflowingBinaryOperator>(Inst)->setHasNoUnsignedOverflow(true); + if (AlsoSigned) + cast<OverflowingBinaryOperator>(Inst)->setHasNoSignedOverflow(true); + } + return Result; + } + return TokError("expected 'add', 'sub', or 'mul'"); + } + case lltok::kw_exact: + if (Lex.getKind() == lltok::kw_sdiv) { + Lex.Lex(); + KeywordVal = Lex.getUIntVal(); + bool Result = ParseArithmetic(Inst, PFS, KeywordVal, 1); + if (!Result) + cast<SDivOperator>(Inst)->setIsExact(true); + return Result; + } + return TokError("expected 'udiv'"); case lltok::kw_getresult: return ParseGetResult(Inst, PFS); case lltok::kw_getelementptr: return ParseGetElementPtr(Inst, PFS); case lltok::kw_extractvalue: return ParseExtractValue(Inst, PFS); diff --git a/lib/AsmParser/LLToken.h b/lib/AsmParser/LLToken.h index 0f00eb63b0..b78a09d43e 100644 --- a/lib/AsmParser/LLToken.h +++ b/lib/AsmParser/LLToken.h @@ -51,6 +51,9 @@ namespace lltok { kw_deplibs, kw_datalayout, kw_volatile, + kw_signed, + kw_unsigned, + kw_exact, kw_align, kw_addrspace, kw_section, diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp index bc1eba01e2..95276b1aec 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -20,6 +20,7 @@ #include "llvm/LLVMContext.h" #include "llvm/MDNode.h" #include "llvm/Module.h" +#include "llvm/Operator.h" #include "llvm/AutoUpgrade.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" @@ -747,6 +748,18 @@ bool BitcodeReader::ResolveGlobalAndAliasInits() { return false; } +static void SetOptimizationFlags(Value *V, uint64_t Flags) { + if (OverflowingBinaryOperator *OBO = + dyn_cast<OverflowingBinaryOperator>(V)) { + if (Flags & (1 << bitc::OBO_NO_SIGNED_OVERFLOW)) + OBO->setHasNoSignedOverflow(true); + if (Flags & (1 << bitc::OBO_NO_UNSIGNED_OVERFLOW)) + OBO->setHasNoUnsignedOverflow(true); + } else if (SDivOperator *Div = dyn_cast<SDivOperator>(V)) { + if (Flags & (1 << bitc::SDIV_EXACT)) + Div->setIsExact(true); + } +} bool BitcodeReader::ParseConstants() { if (Stream.EnterSubBlock(bitc::CONSTANTS_BLOCK_ID)) @@ -778,7 +791,8 @@ bool BitcodeReader::ParseConstants() { // Read a record. Record.clear(); Value *V = 0; - switch (Stream.ReadRecord(Code, Record)) { + unsigned BitCode = Stream.ReadRecord(Code, Record); + switch (BitCode) { default: // Default behavior: unknown constant case bitc::CST_CODE_UNDEF: // UNDEF V = Context.getUndef(CurTy); @@ -899,6 +913,8 @@ bool BitcodeReader::ParseConstants() { Constant *RHS = ValueList.getConstantFwdRef(Record[2], CurTy); V = Context.getConstantExpr(Opc, LHS, RHS); } + if (Record.size() >= 4) + SetOptimizationFlags(V, Record[3]); break; } case bitc::CST_CODE_CE_CAST: { // CE_CAST: [opcode, opty, opval] @@ -1451,7 +1467,8 @@ bool BitcodeReader::ParseFunctionBody(Function *F) { // Read a record. Record.clear(); Instruction *I = 0; - switch (Stream.ReadRecord(Code, Record)) { + unsigned BitCode = Stream.ReadRecord(Code, Record); + switch (BitCode) { default: // Default behavior: reject return Error("Unknown instruction"); case bitc::FUNC_CODE_DECLAREBLOCKS: // DECLAREBLOCKS: [nblocks] @@ -1469,12 +1486,14 @@ bool BitcodeReader::ParseFunctionBody(Function *F) { Value *LHS, *RHS; if (getValueTypePair(Record, OpNum, NextValueNo, LHS) || getValue(Record, OpNum, LHS->getType(), RHS) || - OpNum+1 != Record.size()) + OpNum+1 > Record.size()) return Error("Invalid BINOP record"); - int Opc = GetDecodedBinaryOpcode(Record[OpNum], LHS->getType()); + int Opc = GetDecodedBinaryOpcode(Record[OpNum++], LHS->getType()); if (Opc == -1) return Error("Invalid BINOP record"); I = BinaryOperator::Create((Instruction::BinaryOps)Opc, LHS, RHS); + if (OpNum < Record.size()) + SetOptimizationFlags(I, Record[3]); break; } case bitc::FUNC_CODE_INST_CAST: { // CAST: [opval, opty, destty, castopc] diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index d7acd14a80..d245e5bcb1 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -21,6 +21,7 @@ #include "llvm/Instructions.h" #include "llvm/MDNode.h" #include "llvm/Module.h" +#include "llvm/Operator.h" #include "llvm/TypeSymbolTable.h" #include "llvm/ValueSymbolTable.h" #include "llvm/Support/ErrorHandling.h" @@ -50,6 +51,7 @@ enum { // FUNCTION_BLOCK abbrev id's. FUNCTION_INST_LOAD_ABBREV = bitc::FIRST_APPLICATION_ABBREV, FUNCTION_INST_BINOP_ABBREV, + FUNCTION_INST_BINOP_FLAGS_ABBREV, FUNCTION_INST_CAST_ABBREV, FUNCTION_INST_RET_VOID_ABBREV, FUNCTION_INST_RET_VAL_ABBREV, @@ -454,6 +456,22 @@ static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE, } } +static uint64_t GetOptimizationFlags(const Value *V) { + uint64_t Flags = 0; + + if (const OverflowingBinaryOperator *OBO = + dyn_cast<OverflowingBinaryOperator>(V)) { + if (OBO->hasNoSignedOverflow()) + Flags |= 1 << bitc::OBO_NO_SIGNED_OVERFLOW; + if (OBO->hasNoUnsignedOverflow()) + Flags |= 1 << bitc::OBO_NO_UNSIGNED_OVERFLOW; + } else if (const SDivOperator *Div = dyn_cast<SDivOperator>(V)) { + if (Div->isExact()) + Flags |= 1 << bitc::SDIV_EXACT; + } + + return Flags; +} static void WriteConstants(unsigned FirstVal, unsigned LastVal, const ValueEnumerator &VE, @@ -641,6 +659,9 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal, Record.push_back(GetEncodedBinaryOpcode(CE->getOpcode())); Record.push_back(VE.getValueID(C->getOperand(0))); Record.push_back(VE.getValueID(C->getOperand(1))); + uint64_t Flags = GetOptimizationFlags(CE); + if (Flags != 0) + Record.push_back(Flags); } break; case Instruction::GetElementPtr: @@ -778,6 +799,12 @@ static void WriteInstruction(const Instruction &I, unsigned InstID, AbbrevToUse = FUNCTION_INST_BINOP_ABBREV; Vals.push_back(VE.getValueID(I.getOperand(1))); Vals.push_back(GetEncodedBinaryOpcode(I.getOpcode())); + uint64_t Flags = GetOptimizationFlags(&I); + if (Flags != 0) { + if (AbbrevToUse == FUNCTION_INST_BINOP_ABBREV) + AbbrevToUse = FUNCTION_INST_BINOP_FLAGS_ABBREV; + Vals.push_back(Flags); + } } break; @@ -1225,6 +1252,17 @@ static void WriteBlockInfo(const ValueEnumerator &VE, BitstreamWriter &Stream) { Abbv) != FUNCTION_INST_BINOP_ABBREV) llvm_unreachable("Unexpected abbrev ordering!"); } + { // INST_BINOP_FLAGS abbrev for FUNCTION_BLOCK. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_BINOP)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LHS + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // RHS + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // opc + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 7)); // flags + if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, + Abbv) != FUNCTION_INST_BINOP_FLAGS_ABBREV) + llvm_unreachable("Unexpected abbrev ordering!"); + } { // INST_CAST abbrev for FUNCTION_BLOCK. BitCodeAbbrev *Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_CAST)); diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp index d5f211b14f..a091a935ba 100644 --- a/lib/VMCore/AsmWriter.cpp +++ b/lib/VMCore/AsmWriter.cpp @@ -23,6 +23,7 @@ #include "llvm/InlineAsm.h" #include "llvm/Instruction.h" #include "llvm/Instructions.h" +#include "llvm/Operator.h" #include "llvm/MDNode.h" #include "llvm/Module.h" #include "llvm/ValueSymbolTable.h" @@ -851,6 +852,19 @@ static void WriteMDNodes(raw_ostream &Out, TypePrinting &TypePrinter, } } +static void WriteOptimizationInfo(raw_ostream &Out, const User *U) { + if (const OverflowingBinaryOperator *OBO = + dyn_cast<OverflowingBinaryOperator>(U)) { + if (OBO->hasNoUnsignedOverflow()) + Out << "unsigned "; + if (OBO->hasNoSignedOverflow()) + Out << "signed "; + } else if (const SDivOperator *Div = dyn_cast<SDivOperator>(U)) { + if (Div->isExact()) + Out << "exact "; + } +} + static void WriteConstantInt(raw_ostream &Out, const Constant *CV, TypePrinting &TypePrinter, SlotTracker *Machine) { if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) { @@ -1062,6 +1076,7 @@ static void WriteConstantInt(raw_ostream &Out, const Constant *CV, } if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) { + WriteOptimizationInfo(Out, CE); Out << CE->getOpcodeName(); if (CE->isCompare()) Out << ' ' << getPredicateText(CE->getPredicate()); @@ -1682,6 +1697,9 @@ void AssemblyWriter::printInstruction(const Instruction &I) { Out << "tail "; } + // Print out optimization information. + WriteOptimizationInfo(Out, &I); + // Print out the opcode... Out << I.getOpcodeName(); diff --git a/test/Assembler/flags-plain.ll b/test/Assembler/flags-plain.ll new file mode 100644 index 0000000000..148d02fc06 --- /dev/null +++ b/test/Assembler/flags-plain.ll @@ -0,0 +1,23 @@ +; RUN: llvm-as < %s | llvm-dis | FileCheck %s + +@addr = external global i64 + +define i64 @add_plain_ce() { +; CHECK: ret i64 add (i64 ptrtoint (i64* @addr to i64), i64 91) + ret i64 add (i64 ptrtoint (i64* @addr to i64), i64 91) +} + +define i64 @sub_plain_ce() { +; CHECK: ret i64 sub (i64 ptrtoint (i64* @addr to i64), i64 91) + ret i64 sub (i64 ptrtoint (i64* @addr to i64), i64 91) +} + +define i64 @mul_plain_ce() { +; CHECK: ret i64 mul (i64 ptrtoint (i64* @addr to i64), i64 91) + ret i64 mul (i64 ptrtoint (i64* @addr to i64), i64 91) +} + +define i64 @sdiv_plain_ce() { +; CHECK: ret i64 sdiv (i64 ptrtoint (i64* @addr to i64), i64 91) + ret i64 sdiv (i64 ptrtoint (i64* @addr to i64), i64 91) +} diff --git a/test/Assembler/flags-reversed.ll b/test/Assembler/flags-reversed.ll new file mode 100644 index 0000000000..b63ac84953 --- /dev/null +++ b/test/Assembler/flags-reversed.ll @@ -0,0 +1,18 @@ +; RUN: llvm-as < %s | llvm-dis | FileCheck %s + +@addr = external global i64 + +define i64 @add_both_reversed_ce() { +; CHECK: ret i64 unsigned signed add (i64 ptrtoint (i64* @addr to i64), i64 91) + ret i64 signed unsigned add (i64 ptrtoint (i64* @addr to i64), i64 91) +} + +define i64 @sub_both_reversed_ce() { +; CHECK: ret i64 unsigned signed sub (i64 ptrtoint (i64* @addr to i64), i64 91) + ret i64 signed unsigned sub (i64 ptrtoint (i64* @addr to i64), i64 91) +} + +define i64 @mul_both_reversed_ce() { +; CHECK: ret i64 unsigned signed mul (i64 ptrtoint (i64* @addr to i64), i64 91) + ret i64 signed unsigned mul (i64 ptrtoint (i64* @addr to i64), i64 91) +} diff --git a/test/Assembler/flags-signed.ll b/test/Assembler/flags-signed.ll new file mode 100644 index 0000000000..136dd57dd8 --- /dev/null +++ b/test/Assembler/flags-signed.ll @@ -0,0 +1,18 @@ +; RUN: llvm-as < %s | llvm-dis | FileCheck %s + +@addr = external global i64 + +define i64 @add_signed_ce() { +; CHECK: ret i64 signed add (i64 ptrtoint (i64* @addr to i64), i64 91) + ret i64 signed add (i64 ptrtoint (i64* @addr to i64), i64 91) +} + +define i64 @sub_signed_ce() { +; CHECK: ret i64 signed sub (i64 ptrtoint (i64* @addr to i64), i64 91) + ret i64 signed sub (i64 ptrtoint (i64* @addr to i64), i64 91) +} + +define i64 @mul_signed_ce() { +; CHECK: ret i64 signed mul (i64 ptrtoint (i64* @addr to i64), i64 91) + ret i64 signed mul (i64 ptrtoint (i64* @addr to i64), i64 91) +} diff --git a/test/Assembler/flags-unsigned.ll b/test/Assembler/flags-unsigned.ll new file mode 100644 index 0000000000..1526db0770 --- /dev/null +++ b/test/Assembler/flags-unsigned.ll @@ -0,0 +1,18 @@ +; RUN: llvm-as < %s | llvm-dis | FileCheck %s + +@addr = external global i64 + +define i64 @add_unsigned_ce() { +; CHECK: ret i64 unsigned add (i64 ptrtoint (i64* @addr to i64), i64 91) + ret i64 unsigned add (i64 ptrtoint (i64* @addr to i64), i64 91) +} + +define i64 @sub_unsigned_ce() { +; CHECK: ret i64 unsigned sub (i64 ptrtoint (i64* @addr to i64), i64 91) + ret i64 unsigned sub (i64 ptrtoint (i64* @addr to i64), i64 91) +} + +define i64 @mul_unsigned_ce() { +; CHECK: ret i64 unsigned mul (i64 ptrtoint (i64* @addr to i64), i64 91) + ret i64 unsigned mul (i64 ptrtoint (i64* @addr to i64), i64 91) +} diff --git a/test/Assembler/flags.ll b/test/Assembler/flags.ll new file mode 100644 index 0000000000..317bc0cf1c --- /dev/null +++ b/test/Assembler/flags.ll @@ -0,0 +1,125 @@ +; RUN: llvm-as < %s | llvm-dis | FileCheck %s + +@addr = external global i64 + +define i64 @add_signed(i64 %x, i64 %y) { +; CHECK: %z = signed add i64 %x, %y + %z = signed add i64 %x, %y + ret i64 %z +} + +define i64 @sub_signed(i64 %x, i64 %y) { +; CHECK: %z = signed sub i64 %x, %y + %z = signed sub i64 %x, %y + ret i64 %z +} + +define i64 @mul_signed(i64 %x, i64 %y) { +; CHECK: %z = signed mul i64 %x, %y + %z = signed mul i64 %x, %y + ret i64 %z +} + +define i64 @add_unsigned(i64 %x, i64 %y) { +; CHECK: %z = unsigned add i64 %x, %y + %z = unsigned add i64 %x, %y + ret i64 %z +} + +define i64 @sub_unsigned(i64 %x, i64 %y) { +; CHECK: %z = unsigned sub i64 %x, %y + %z = unsigned sub i64 %x, %y + ret i64 %z +} + +define i64 @mul_unsigned(i64 %x, i64 %y) { +; CHECK: %z = unsigned mul i64 %x, %y + %z = unsigned mul i64 %x, %y + ret i64 %z +} + +define i64 @add_plain(i64 %x, i64 %y) { +; CHECK: %z = add i64 %x, %y + %z = add i64 %x, %y + ret i64 %z +} + +define i64 @sub_plain(i64 %x, i64 %y) { +; CHECK: %z = sub i64 %x, %y + %z = sub i64 %x, %y + ret i64 %z +} + +define i64 @mul_plain(i64 %x, i64 %y) { +; CHECK: %z = mul i64 %x, %y + %z = mul i64 %x, %y + ret i64 %z +} + +define i64 @add_both(i64 %x, i64 %y) { +; CHECK: %z = unsigned signed add i64 %x, %y + %z = unsigned signed add i64 %x, %y + ret i64 %z +} + +define i64 @sub_both(i64 %x, i64 %y) { +; CHECK: %z = unsigned signed sub i64 %x, %y + %z = unsigned signed sub i64 %x, %y + ret i64 %z +} + +define i64 @mul_both(i64 %x, i64 %y) { +; CHECK: %z = unsigned signed mul i64 %x, %y + %z = unsigned signed mul i64 %x, %y + ret i64 %z +} + +define i64 @add_both_reversed(i64 %x, i64 %y) { +; CHECK: %z = unsigned signed add i64 %x, %y + %z = signed unsigned add i64 %x, %y + ret i64 %z +} + +define i64 @sub_both_reversed(i64 %x, i64 %y) { +; CHECK: %z = unsigned signed sub i64 %x, %y + %z = signed unsigned sub i64 %x, %y + ret i64 %z +} + +define i64 @mul_both_reversed(i64 %x, i64 %y) { +; CHECK: %z = unsigned signed mul i64 %x, %y + %z = signed unsigned mul i64 %x, %y + ret i64 %z +} + +define i64 @sdiv_exact(i64 %x, i64 %y) { +; CHECK: %z = exact sdiv i64 %x, %y + %z = exact sdiv i64 %x, %y + ret i64 %z +} + +define i64 @sdiv_plain(i64 %x, i64 %y) { +; CHECK: %z = sdiv i64 %x, %y + %z = sdiv i64 %x, %y + ret i64 %z +} + +define i64 @add_both_ce() { +; CHECK: ret i64 unsigned signed add (i64 ptrtoint (i64* @addr to i64), i64 91) + ret i64 signed unsigned add (i64 ptrtoint (i64* @addr to i64), i64 91) +} + +define i64 @sub_both_ce() { +; CHECK: ret i64 unsigned signed sub (i64 ptrtoint (i64* @addr to i64), i64 91) + ret i64 signed unsigned sub (i64 ptrtoint (i64* @addr to i64), i64 91) +} + +define i64 @mul_both_ce() { +; CHECK: ret i64 unsigned signed mul (i64 ptrtoint (i64* @addr to i64), i64 91) + ret i64 unsigned signed mul (i64 ptrtoint (i64* @addr to i64), i64 91) +} + +define i64 @sdiv_exact_ce() { +; CHECK: ret i64 exact sdiv (i64 ptrtoint (i64* @addr to i64), i64 91) + ret i64 exact sdiv (i64 ptrtoint (i64* @addr to i64), i64 91) +} |