Skip to content
This repository has been archived by the owner on Apr 23, 2020. It is now read-only.

Commit

Permalink
[IR] Add a dedicated FNeg IR Instruction
Browse files Browse the repository at this point in the history
The IEEE-754 Standard makes it clear that fneg(x) and
fsub(-0.0, x) are two different operations. The former is a bitwise
operation, while the latter is an arithmetic operation. This patch
creates a dedicated FNeg IR Instruction to model that behavior.

Differential Revision: https://reviews.llvm.org/D53877



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@346774 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
mcinally committed Nov 13, 2018
1 parent 3eec80d commit ca8cb68
Show file tree
Hide file tree
Showing 30 changed files with 595 additions and 83 deletions.
5 changes: 5 additions & 0 deletions include/llvm-c/Core.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ extern "C" {
* @{
*/

/// External users depend on the following values being stable. It is not safe
/// to reorder them.
typedef enum {
/* Terminator Instructions */
LLVMRet = 1,
Expand All @@ -64,6 +66,9 @@ typedef enum {
/* removed 6 due to API changes */
LLVMUnreachable = 7,

/* Standard Unary Operators */
LLVMFNeg = 66,

/* Standard Binary Operators */
LLVMAdd = 8,
LLVMFAdd = 9,
Expand Down
10 changes: 10 additions & 0 deletions include/llvm/Bitcode/LLVMBitCodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,7 @@ enum ConstantsCodes {
CST_CODE_INLINEASM = 23, // INLINEASM: [sideeffect|alignstack|
// asmdialect,asmstr,conststr]
CST_CODE_CE_GEP_WITH_INRANGE_INDEX = 24, // [opty, flags, n x operands]
CST_CODE_CE_UNOP = 25, // CE_UNOP: [opcode, opval]
};

/// CastOpcodes - These are values used in the bitcode files to encode which
Expand All @@ -364,6 +365,14 @@ enum CastOpcodes {
CAST_ADDRSPACECAST = 12
};

/// UnaryOpcodes - These are values used in the bitcode files to encode which
/// unop a CST_CODE_CE_UNOP or a XXX refers to. The values of these enums
/// have no fixed relation to the LLVM IR enum values. Changing these will
/// break compatibility with old files.
enum UnaryOpcodes {
UNOP_NEG = 0
};

/// BinaryOpcodes - These are values used in the bitcode files to encode which
/// binop a CST_CODE_CE_BINOP or a XXX refers to. The values of these enums
/// have no fixed relation to the LLVM IR enum values. Changing these will
Expand Down Expand Up @@ -524,6 +533,7 @@ enum FunctionCodes {
// 53 is unused.
// 54 is unused.
FUNC_CODE_OPERAND_BUNDLE = 55, // OPERAND_BUNDLE: [tag#, value...]
FUNC_CODE_INST_UNOP = 56, // UNOP: [opcode, ty, opval]
};

enum UseListCodes {
Expand Down
2 changes: 2 additions & 0 deletions include/llvm/CodeGen/GlobalISel/IRTranslator.h
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,8 @@ class IRTranslator : public MachineFunctionPass {

bool translateFSub(const User &U, MachineIRBuilder &MIRBuilder);

bool translateFNeg(const User &U, MachineIRBuilder &MIRBuilder);

bool translateAdd(const User &U, MachineIRBuilder &MIRBuilder) {
return translateBinaryOp(TargetOpcode::G_ADD, U, MIRBuilder);
}
Expand Down
7 changes: 7 additions & 0 deletions include/llvm/IR/Constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -1114,6 +1114,13 @@ class ConstantExpr : public Constant {
static Constant *getSelect(Constant *C, Constant *V1, Constant *V2,
Type *OnlyIfReducedTy = nullptr);

/// get - Return a unary operator constant expression,
/// folding if possible.
///
/// \param OnlyIfReducedTy see \a getWithOperands() docs.
static Constant *get(unsigned Opcode, Constant *C1, unsigned Flags = 0,
Type *OnlyIfReducedTy = nullptr);

/// get - Return a binary or shift operator constant expression,
/// folding if possible.
///
Expand Down
1 change: 1 addition & 0 deletions include/llvm/IR/InstVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ class InstVisitor {
// of instructions...
//
RetTy visitCastInst(CastInst &I) { DELEGATE(UnaryInstruction);}
RetTy visitUnaryOperator(UnaryOperator &I) { DELEGATE(UnaryInstruction);}
RetTy visitBinaryOperator(BinaryOperator &I) { DELEGATE(Instruction);}
RetTy visitCmpInst(CmpInst &I) { DELEGATE(Instruction);}
RetTy visitUnaryInstruction(UnaryInstruction &I){ DELEGATE(Instruction);}
Expand Down
153 changes: 88 additions & 65 deletions include/llvm/IR/Instruction.def
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,20 @@
#define LAST_TERM_INST(num)
#endif

#ifndef FIRST_UNARY_INST
#define FIRST_UNARY_INST(num)
#endif
#ifndef HANDLE_UNARY_INST
#ifndef HANDLE_INST
#define HANDLE_UNARY_INST(num, opcode, instclass)
#else
#define HANDLE_UNARY_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class)
#endif
#endif
#ifndef LAST_UNARY_INST
#define LAST_UNARY_INST(num)
#endif

#ifndef FIRST_BINARY_INST
#define FIRST_BINARY_INST(num)
#endif
Expand Down Expand Up @@ -123,87 +137,96 @@ HANDLE_TERM_INST ( 9, CatchRet , CatchReturnInst)
HANDLE_TERM_INST (10, CatchSwitch , CatchSwitchInst)
LAST_TERM_INST (10)

// Standard unary operators...
FIRST_UNARY_INST(11)
HANDLE_UNARY_INST(11, FNeg , UnaryOperator)
LAST_UNARY_INST(11)

// Standard binary operators...
FIRST_BINARY_INST(11)
HANDLE_BINARY_INST(11, Add , BinaryOperator)
HANDLE_BINARY_INST(12, FAdd , BinaryOperator)
HANDLE_BINARY_INST(13, Sub , BinaryOperator)
HANDLE_BINARY_INST(14, FSub , BinaryOperator)
HANDLE_BINARY_INST(15, Mul , BinaryOperator)
HANDLE_BINARY_INST(16, FMul , BinaryOperator)
HANDLE_BINARY_INST(17, UDiv , BinaryOperator)
HANDLE_BINARY_INST(18, SDiv , BinaryOperator)
HANDLE_BINARY_INST(19, FDiv , BinaryOperator)
HANDLE_BINARY_INST(20, URem , BinaryOperator)
HANDLE_BINARY_INST(21, SRem , BinaryOperator)
HANDLE_BINARY_INST(22, FRem , BinaryOperator)
FIRST_BINARY_INST(12)
HANDLE_BINARY_INST(12, Add , BinaryOperator)
HANDLE_BINARY_INST(13, FAdd , BinaryOperator)
HANDLE_BINARY_INST(14, Sub , BinaryOperator)
HANDLE_BINARY_INST(15, FSub , BinaryOperator)
HANDLE_BINARY_INST(16, Mul , BinaryOperator)
HANDLE_BINARY_INST(17, FMul , BinaryOperator)
HANDLE_BINARY_INST(18, UDiv , BinaryOperator)
HANDLE_BINARY_INST(19, SDiv , BinaryOperator)
HANDLE_BINARY_INST(20, FDiv , BinaryOperator)
HANDLE_BINARY_INST(21, URem , BinaryOperator)
HANDLE_BINARY_INST(22, SRem , BinaryOperator)
HANDLE_BINARY_INST(23, FRem , BinaryOperator)

// Logical operators (integer operands)
HANDLE_BINARY_INST(23, Shl , BinaryOperator) // Shift left (logical)
HANDLE_BINARY_INST(24, LShr , BinaryOperator) // Shift right (logical)
HANDLE_BINARY_INST(25, AShr , BinaryOperator) // Shift right (arithmetic)
HANDLE_BINARY_INST(26, And , BinaryOperator)
HANDLE_BINARY_INST(27, Or , BinaryOperator)
HANDLE_BINARY_INST(28, Xor , BinaryOperator)
LAST_BINARY_INST(28)
HANDLE_BINARY_INST(24, Shl , BinaryOperator) // Shift left (logical)
HANDLE_BINARY_INST(25, LShr , BinaryOperator) // Shift right (logical)
HANDLE_BINARY_INST(26, AShr , BinaryOperator) // Shift right (arithmetic)
HANDLE_BINARY_INST(27, And , BinaryOperator)
HANDLE_BINARY_INST(28, Or , BinaryOperator)
HANDLE_BINARY_INST(29, Xor , BinaryOperator)
LAST_BINARY_INST(29)

// Memory operators...
FIRST_MEMORY_INST(29)
HANDLE_MEMORY_INST(29, Alloca, AllocaInst) // Stack management
HANDLE_MEMORY_INST(30, Load , LoadInst ) // Memory manipulation instrs
HANDLE_MEMORY_INST(31, Store , StoreInst )
HANDLE_MEMORY_INST(32, GetElementPtr, GetElementPtrInst)
HANDLE_MEMORY_INST(33, Fence , FenceInst )
HANDLE_MEMORY_INST(34, AtomicCmpXchg , AtomicCmpXchgInst )
HANDLE_MEMORY_INST(35, AtomicRMW , AtomicRMWInst )
LAST_MEMORY_INST(35)
FIRST_MEMORY_INST(30)
HANDLE_MEMORY_INST(30, Alloca, AllocaInst) // Stack management
HANDLE_MEMORY_INST(31, Load , LoadInst ) // Memory manipulation instrs
HANDLE_MEMORY_INST(32, Store , StoreInst )
HANDLE_MEMORY_INST(33, GetElementPtr, GetElementPtrInst)
HANDLE_MEMORY_INST(34, Fence , FenceInst )
HANDLE_MEMORY_INST(35, AtomicCmpXchg , AtomicCmpXchgInst )
HANDLE_MEMORY_INST(36, AtomicRMW , AtomicRMWInst )
LAST_MEMORY_INST(36)

// Cast operators ...
// NOTE: The order matters here because CastInst::isEliminableCastPair
// NOTE: (see Instructions.cpp) encodes a table based on this ordering.
FIRST_CAST_INST(36)
HANDLE_CAST_INST(36, Trunc , TruncInst ) // Truncate integers
HANDLE_CAST_INST(37, ZExt , ZExtInst ) // Zero extend integers
HANDLE_CAST_INST(38, SExt , SExtInst ) // Sign extend integers
HANDLE_CAST_INST(39, FPToUI , FPToUIInst ) // floating point -> UInt
HANDLE_CAST_INST(40, FPToSI , FPToSIInst ) // floating point -> SInt
HANDLE_CAST_INST(41, UIToFP , UIToFPInst ) // UInt -> floating point
HANDLE_CAST_INST(42, SIToFP , SIToFPInst ) // SInt -> floating point
HANDLE_CAST_INST(43, FPTrunc , FPTruncInst ) // Truncate floating point
HANDLE_CAST_INST(44, FPExt , FPExtInst ) // Extend floating point
HANDLE_CAST_INST(45, PtrToInt, PtrToIntInst) // Pointer -> Integer
HANDLE_CAST_INST(46, IntToPtr, IntToPtrInst) // Integer -> Pointer
HANDLE_CAST_INST(47, BitCast , BitCastInst ) // Type cast
HANDLE_CAST_INST(48, AddrSpaceCast, AddrSpaceCastInst) // addrspace cast
LAST_CAST_INST(48)

FIRST_FUNCLETPAD_INST(49)
HANDLE_FUNCLETPAD_INST(49, CleanupPad, CleanupPadInst)
HANDLE_FUNCLETPAD_INST(50, CatchPad , CatchPadInst)
LAST_FUNCLETPAD_INST(50)
FIRST_CAST_INST(37)
HANDLE_CAST_INST(37, Trunc , TruncInst ) // Truncate integers
HANDLE_CAST_INST(38, ZExt , ZExtInst ) // Zero extend integers
HANDLE_CAST_INST(39, SExt , SExtInst ) // Sign extend integers
HANDLE_CAST_INST(40, FPToUI , FPToUIInst ) // floating point -> UInt
HANDLE_CAST_INST(41, FPToSI , FPToSIInst ) // floating point -> SInt
HANDLE_CAST_INST(42, UIToFP , UIToFPInst ) // UInt -> floating point
HANDLE_CAST_INST(43, SIToFP , SIToFPInst ) // SInt -> floating point
HANDLE_CAST_INST(44, FPTrunc , FPTruncInst ) // Truncate floating point
HANDLE_CAST_INST(45, FPExt , FPExtInst ) // Extend floating point
HANDLE_CAST_INST(46, PtrToInt, PtrToIntInst) // Pointer -> Integer
HANDLE_CAST_INST(47, IntToPtr, IntToPtrInst) // Integer -> Pointer
HANDLE_CAST_INST(48, BitCast , BitCastInst ) // Type cast
HANDLE_CAST_INST(49, AddrSpaceCast, AddrSpaceCastInst) // addrspace cast
LAST_CAST_INST(49)

FIRST_FUNCLETPAD_INST(50)
HANDLE_FUNCLETPAD_INST(50, CleanupPad, CleanupPadInst)
HANDLE_FUNCLETPAD_INST(51, CatchPad , CatchPadInst)
LAST_FUNCLETPAD_INST(51)

// Other operators...
FIRST_OTHER_INST(51)
HANDLE_OTHER_INST(51, ICmp , ICmpInst ) // Integer comparison instruction
HANDLE_OTHER_INST(52, FCmp , FCmpInst ) // Floating point comparison instr.
HANDLE_OTHER_INST(53, PHI , PHINode ) // PHI node instruction
HANDLE_OTHER_INST(54, Call , CallInst ) // Call a function
HANDLE_OTHER_INST(55, Select , SelectInst ) // select instruction
HANDLE_USER_INST (56, UserOp1, Instruction) // May be used internally in a pass
HANDLE_USER_INST (57, UserOp2, Instruction) // Internal to passes only
HANDLE_OTHER_INST(58, VAArg , VAArgInst ) // vaarg instruction
HANDLE_OTHER_INST(59, ExtractElement, ExtractElementInst)// extract from vector
HANDLE_OTHER_INST(60, InsertElement, InsertElementInst) // insert into vector
HANDLE_OTHER_INST(61, ShuffleVector, ShuffleVectorInst) // shuffle two vectors.
HANDLE_OTHER_INST(62, ExtractValue, ExtractValueInst)// extract from aggregate
HANDLE_OTHER_INST(63, InsertValue, InsertValueInst) // insert into aggregate
HANDLE_OTHER_INST(64, LandingPad, LandingPadInst) // Landing pad instruction.
LAST_OTHER_INST(64)
FIRST_OTHER_INST(52)
HANDLE_OTHER_INST(52, ICmp , ICmpInst ) // Integer comparison instruction
HANDLE_OTHER_INST(53, FCmp , FCmpInst ) // Floating point comparison instr.
HANDLE_OTHER_INST(54, PHI , PHINode ) // PHI node instruction
HANDLE_OTHER_INST(55, Call , CallInst ) // Call a function
HANDLE_OTHER_INST(56, Select , SelectInst ) // select instruction
HANDLE_USER_INST (57, UserOp1, Instruction) // May be used internally in a pass
HANDLE_USER_INST (58, UserOp2, Instruction) // Internal to passes only
HANDLE_OTHER_INST(59, VAArg , VAArgInst ) // vaarg instruction
HANDLE_OTHER_INST(60, ExtractElement, ExtractElementInst)// extract from vector
HANDLE_OTHER_INST(61, InsertElement, InsertElementInst) // insert into vector
HANDLE_OTHER_INST(62, ShuffleVector, ShuffleVectorInst) // shuffle two vectors.
HANDLE_OTHER_INST(63, ExtractValue, ExtractValueInst)// extract from aggregate
HANDLE_OTHER_INST(64, InsertValue, InsertValueInst) // insert into aggregate
HANDLE_OTHER_INST(65, LandingPad, LandingPadInst) // Landing pad instruction.
LAST_OTHER_INST(65)

#undef FIRST_TERM_INST
#undef HANDLE_TERM_INST
#undef LAST_TERM_INST

#undef FIRST_UNARY_INST
#undef HANDLE_UNARY_INST
#undef LAST_UNARY_INST

#undef FIRST_BINARY_INST
#undef HANDLE_BINARY_INST
#undef LAST_BINARY_INST
Expand Down
11 changes: 11 additions & 0 deletions include/llvm/IR/Instruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ class Instruction : public User,

const char *getOpcodeName() const { return getOpcodeName(getOpcode()); }
bool isTerminator() const { return isTerminator(getOpcode()); }
bool isUnaryOp() const { return isUnaryOp(getOpcode()); }
bool isBinaryOp() const { return isBinaryOp(getOpcode()); }
bool isIntDivRem() const { return isIntDivRem(getOpcode()); }
bool isShift() { return isShift(getOpcode()); }
Expand All @@ -142,6 +143,9 @@ class Instruction : public User,
return OpCode >= TermOpsBegin && OpCode < TermOpsEnd;
}

static inline bool isUnaryOp(unsigned Opcode) {
return Opcode >= UnaryOpsBegin && Opcode < UnaryOpsEnd;
}
static inline bool isBinaryOp(unsigned Opcode) {
return Opcode >= BinaryOpsBegin && Opcode < BinaryOpsEnd;
}
Expand Down Expand Up @@ -662,6 +666,13 @@ class Instruction : public User,
#include "llvm/IR/Instruction.def"
};

enum UnaryOps {
#define FIRST_UNARY_INST(N) UnaryOpsBegin = N,
#define HANDLE_UNARY_INST(N, OPC, CLASS) OPC = N,
#define LAST_UNARY_INST(N) UnaryOpsEnd = N+1
#include "llvm/IR/Instruction.def"
};

enum BinaryOps {
#define FIRST_BINARY_INST(N) BinaryOpsBegin = N,
#define HANDLE_BINARY_INST(N, OPC, CLASS) OPC = N,
Expand Down
65 changes: 65 additions & 0 deletions include/llvm/IR/Instructions.h
Original file line number Diff line number Diff line change
Expand Up @@ -1103,6 +1103,71 @@ GetElementPtrInst::GetElementPtrInst(Type *PointeeType, Value *Ptr,

DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GetElementPtrInst, Value)

//===----------------------------------------------------------------------===//
// UnaryOperator Class
//===----------------------------------------------------------------------===//

/// a unary instruction
class UnaryOperator : public UnaryInstruction {
void AssertOK();

protected:
UnaryOperator(UnaryOps iType, Value *S, Type *Ty,
const Twine &Name, Instruction *InsertBefore);
UnaryOperator(UnaryOps iType, Value *S, Type *Ty,
const Twine &Name, BasicBlock *InsertAtEnd);

// Note: Instruction needs to be a friend here to call cloneImpl.
friend class Instruction;

UnaryOperator *cloneImpl() const;

public:

/// Construct a unary instruction, given the opcode and an operand.
/// Optionally (if InstBefore is specified) insert the instruction
/// into a BasicBlock right before the specified instruction. The specified
/// Instruction is allowed to be a dereferenced end iterator.
///
static UnaryOperator *Create(UnaryOps Op, Value *S,
const Twine &Name = Twine(),
Instruction *InsertBefore = nullptr);

/// Construct a unary instruction, given the opcode and an operand.
/// Also automatically insert this instruction to the end of the
/// BasicBlock specified.
///
static UnaryOperator *Create(UnaryOps Op, Value *S,
const Twine &Name,
BasicBlock *InsertAtEnd);

/// These methods just forward to Create, and are useful when you
/// statically know what type of instruction you're going to create. These
/// helpers just save some typing.
#define HANDLE_UNARY_INST(N, OPC, CLASS) \
static UnaryInstruction *Create##OPC(Value *V, \
const Twine &Name = "") {\
return Create(Instruction::OPC, V, Name);\
}
#include "llvm/IR/Instruction.def"
#define HANDLE_UNARY_INST(N, OPC, CLASS) \
static UnaryInstruction *Create##OPC(Value *V, \
const Twine &Name, BasicBlock *BB) {\
return Create(Instruction::OPC, V, Name, BB);\
}
#include "llvm/IR/Instruction.def"
#define HANDLE_UNARY_INST(N, OPC, CLASS) \
static UnaryInstruction *Create##OPC(Value *V, \
const Twine &Name, Instruction *I) {\
return Create(Instruction::OPC, V, Name, I);\
}
#include "llvm/IR/Instruction.def"

UnaryOps getOpcode() const {
return static_cast<UnaryOps>(Instruction::getOpcode());
}
};

//===----------------------------------------------------------------------===//
// ICmpInst Class
//===----------------------------------------------------------------------===//
Expand Down
2 changes: 2 additions & 0 deletions lib/AsmParser/LLLexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -823,6 +823,8 @@ lltok::Kind LLLexer::LexIdentifier() {
} \
} while (false)

INSTKEYWORD(fneg, FNeg);

INSTKEYWORD(add, Add); INSTKEYWORD(fadd, FAdd);
INSTKEYWORD(sub, Sub); INSTKEYWORD(fsub, FSub);
INSTKEYWORD(mul, Mul); INSTKEYWORD(fmul, FMul);
Expand Down

0 comments on commit ca8cb68

Please sign in to comment.