1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-18 18:42:46 +02:00

For PR950:

This patch converts the old SHR instruction into two instructions,
AShr (Arithmetic) and LShr (Logical). The Shr instructions now are not
dependent on the sign of their operands.

llvm-svn: 31542
This commit is contained in:
Reid Spencer 2006-11-08 06:47:33 +00:00
parent 907d191104
commit da1f5b882a
29 changed files with 4490 additions and 3325 deletions

View File

@ -92,7 +92,8 @@
<li><a href="#i_or">'<tt>or</tt>' Instruction</a></li>
<li><a href="#i_xor">'<tt>xor</tt>' Instruction</a></li>
<li><a href="#i_shl">'<tt>shl</tt>' Instruction</a></li>
<li><a href="#i_shr">'<tt>shr</tt>' Instruction</a></li>
<li><a href="#i_lshr">'<tt>lshr</tt>' Instruction</a></li>
<li><a href="#i_ashr">'<tt>ashr</tt>' Instruction</a></li>
</ol>
</li>
<li><a href="#vectorops">Vector Operations</a>
@ -2070,30 +2071,64 @@ type.</p>
</pre>
</div>
<!-- _______________________________________________________________________ -->
<div class="doc_subsubsection"> <a name="i_shr">'<tt>shr</tt>'
<div class="doc_subsubsection"> <a name="i_lshr">'<tt>lshr</tt>'
Instruction</a> </div>
<div class="doc_text">
<h5>Syntax:</h5>
<pre> &lt;result&gt; = shr &lt;ty&gt; &lt;var1&gt;, ubyte &lt;var2&gt; <i>; yields {ty}:result</i>
<pre> &lt;result&gt; = lshr &lt;ty&gt; &lt;var1&gt;, ubyte &lt;var2&gt; <i>; yields {ty}:result</i>
</pre>
<h5>Overview:</h5>
<p>The '<tt>shr</tt>' instruction returns the first operand shifted to
the right a specified number of bits.</p>
<p>The '<tt>lshr</tt>' instruction (logical shift right) returns the first
operand shifted to the right a specified number of bits.</p>
<h5>Arguments:</h5>
<p>The first argument to the '<tt>shr</tt>' instruction must be an <a
href="#t_integer">integer</a> type. The second argument must be an '<tt>ubyte</tt>'
type.</p>
<p>The first argument to the '<tt>lshr</tt>' instruction must be an <a
href="#t_integer">integer</a> type. The second argument must be an '<tt>ubyte</tt>' type.</p>
<h5>Semantics:</h5>
<p>If the first argument is a <a href="#t_signed">signed</a> type, the
most significant bit is duplicated in the newly free'd bit positions.
If the first argument is unsigned, zero bits shall fill the empty
positions.</p>
<p>This instruction always performs a logical shift right operation, regardless
of whether the arguments are unsigned or not. The <tt>var2</tt> most significant
bits will be filled with zero bits after the shift.</p>
<h5>Example:</h5>
<pre> &lt;result&gt; = shr int 4, ubyte %var <i>; yields {int}:result = 4 &gt;&gt; %var</i>
&lt;result&gt; = shr uint 4, ubyte 1 <i>; yields {uint}:result = 2</i>
&lt;result&gt; = shr int 4, ubyte 2 <i>; yields {int}:result = 1</i>
&lt;result&gt; = shr sbyte 4, ubyte 3 <i>; yields {sbyte}:result = 0</i>
&lt;result&gt; = shr sbyte -2, ubyte 1 <i>; yields {sbyte}:result = -1</i>
<pre>
&lt;result&gt; = lshr uint 4, ubyte 1 <i>; yields {uint}:result = 2</i>
&lt;result&gt; = lshr int 4, ubyte 2 <i>; yields {uint}:result = 1</i>
&lt;result&gt; = lshr sbyte 4, ubyte 3 <i>; yields {sbyte}:result = 0</i>
&lt;result&gt; = lshr sbyte -2, ubyte 1 <i>; yields {sbyte}:result = 0x7FFFFFFF </i>
</pre>
</div>
<!-- ======================================================================= -->
<div class="doc_subsubsection"> <a name="i_ashr">'<tt>ashr</tt>'
Instruction</a> </div>
<div class="doc_text">
<h5>Syntax:</h5>
<pre> &lt;result&gt; = ashr &lt;ty&gt; &lt;var1&gt;, ubyte &lt;var2&gt; <i>; yields {ty}:result</i>
</pre>
<h5>Overview:</h5>
<p>The '<tt>ashr</tt>' instruction (arithmetic shift right) returns the first
operand shifted to the right a specified number of bits.</p>
<h5>Arguments:</h5>
<p>The first argument to the '<tt>ashr</tt>' instruction must be an
<a href="#t_integer">integer</a> type. The second argument must be an
'<tt>ubyte</tt>' type.</p>
<h5>Semantics:</h5>
<p>This instruction always performs an arithmetic shift right operation,
regardless of whether the arguments are signed or not. The <tt>var2</tt> most
significant bits will be filled with the sign bit of <tt>var1</tt>.</p>
<h5>Example:</h5>
<pre>
&lt;result&gt; = ashr uint 4, ubyte 1 <i>; yields {uint}:result = 2</i>
&lt;result&gt; = ashr int 4, ubyte 2 <i>; yields {int}:result = 1</i>
&lt;result&gt; = ashr ubyte 4, ubyte 3 <i>; yields {ubyte}:result = 0</i>
&lt;result&gt; = ashr sbyte -2, ubyte 1 <i>; yields {sbyte}:result = -1</i>
</pre>
</div>

View File

@ -564,10 +564,8 @@ public:
static Constant *getSetLE(Constant *C1, Constant *C2);
static Constant *getSetGE(Constant *C1, Constant *C2);
static Constant *getShl(Constant *C1, Constant *C2);
static Constant *getShr(Constant *C1, Constant *C2);
static Constant *getUShr(Constant *C1, Constant *C2); // unsigned shr
static Constant *getSShr(Constant *C1, Constant *C2); // signed shr
static Constant *getLShr(Constant *C1, Constant *C2);
static Constant *getAShr(Constant *C1, Constant *C2);
/// Getelementptr form. std::vector<Value*> is only accepted for convenience:
/// all elements must be Constant's.

View File

@ -15,8 +15,8 @@
// NOTE: NO INCLUDE GUARD DESIRED!
// Provide definitions of macros so that users of this file do not have to define
// everything to use it...
// Provide definitions of macros so that users of this file do not have to
// define everything to use it...
//
#ifndef FIRST_TERM_INST
#define FIRST_TERM_INST(num)
@ -129,16 +129,17 @@ HANDLE_MEMORY_INST(30, GetElementPtr, GetElementPtrInst)
HANDLE_OTHER_INST(31, PHI , PHINode ) // PHI node instruction
HANDLE_OTHER_INST(32, Cast , CastInst ) // Type cast
HANDLE_OTHER_INST(33, Call , CallInst ) // Call a function
HANDLE_OTHER_INST(34, Shl , ShiftInst ) // Shift operations
HANDLE_OTHER_INST(35, Shr , ShiftInst )
HANDLE_OTHER_INST(36, Select , SelectInst ) // select instruction
HANDLE_OTHER_INST(37, UserOp1, Instruction) // May be used internally in a pass
HANDLE_OTHER_INST(38, UserOp2, Instruction)
HANDLE_OTHER_INST(39, VAArg , VAArgInst ) // vaarg instruction
HANDLE_OTHER_INST(40, ExtractElement, ExtractElementInst)// extract from vector.
HANDLE_OTHER_INST(41, InsertElement, InsertElementInst) // insert into vector
HANDLE_OTHER_INST(42, ShuffleVector, ShuffleVectorInst) // shuffle two vectors.
LAST_OTHER_INST(42)
HANDLE_OTHER_INST(34, Shl , ShiftInst ) // Shift Left operations (logical)
HANDLE_OTHER_INST(35, LShr , ShiftInst ) // Logical Shift right (unsigned)
HANDLE_OTHER_INST(36, AShr , ShiftInst ) // Arithmetic shift right (signed)
HANDLE_OTHER_INST(37, Select , SelectInst ) // select instruction
HANDLE_OTHER_INST(38, UserOp1, Instruction) // May be used internally in a pass
HANDLE_OTHER_INST(39, UserOp2, Instruction) // Internal to passes only
HANDLE_OTHER_INST(40, VAArg , VAArgInst ) // vaarg instruction
HANDLE_OTHER_INST(41, ExtractElement, ExtractElementInst)// extract from vector.
HANDLE_OTHER_INST(42, InsertElement, InsertElementInst) // insert into vector
HANDLE_OTHER_INST(43, ShuffleVector, ShuffleVectorInst) // shuffle two vectors.
LAST_OTHER_INST(43)
#undef FIRST_TERM_INST
#undef HANDLE_TERM_INST

View File

@ -604,7 +604,8 @@ class ShiftInst : public Instruction {
Ops[1].init(SI.Ops[1], this);
}
void init(OtherOps Opcode, Value *S, Value *SA) {
assert((Opcode == Shl || Opcode == Shr) && "ShiftInst Opcode invalid!");
assert((Opcode == Shl || Opcode == LShr || Opcode == AShr) &&
"ShiftInst Opcode invalid!");
Ops[0].init(S, this);
Ops[1].init(SA, this);
}
@ -638,7 +639,11 @@ public:
/// isLogicalShift - Return true if this is a logical shift left or a logical
/// shift right.
bool isLogicalShift() const;
bool isLogicalShift() const {
unsigned opcode = getOpcode();
return opcode == Instruction::Shl || opcode == Instruction::LShr;
}
/// isArithmeticShift - Return true if this is a sign-extending shift right
/// operation.
@ -652,7 +657,8 @@ public:
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const ShiftInst *) { return true; }
static inline bool classof(const Instruction *I) {
return (I->getOpcode() == Instruction::Shr) |
return (I->getOpcode() == Instruction::LShr) |
(I->getOpcode() == Instruction::AShr) |
(I->getOpcode() == Instruction::Shl);
}
static inline bool classof(const Value *V) {

View File

@ -172,9 +172,49 @@ inline BinaryOp_match<LHS, RHS, Instruction::Shl,
}
template<typename LHS, typename RHS>
inline BinaryOp_match<LHS, RHS, Instruction::Shr,
ShiftInst> m_Shr(const LHS &L, const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::Shr, ShiftInst>(L, R);
inline BinaryOp_match<LHS, RHS, Instruction::LShr,
ShiftInst> m_LShr(const LHS &L, const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::LShr, ShiftInst>(L, R);
}
template<typename LHS, typename RHS>
inline BinaryOp_match<LHS, RHS, Instruction::AShr,
ShiftInst> m_AShr(const LHS &L, const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::AShr, ShiftInst>(L, R);
}
//===----------------------------------------------------------------------===//
// Matchers for either AShr or LShr .. for convenience
//
template<typename LHS_t, typename RHS_t, typename ConcreteTy = ShiftInst>
struct Shr_match {
LHS_t L;
RHS_t R;
Shr_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {}
template<typename OpTy>
bool match(OpTy *V) {
if (V->getValueType() == Value::InstructionVal + Instruction::LShr ||
V->getValueType() == Value::InstructionVal + Instruction::AShr) {
ConcreteTy *I = cast<ConcreteTy>(V);
return (I->getOpcode() == Instruction::AShr ||
I->getOpcode() == Instruction::LShr) &&
L.match(I->getOperand(0)) &&
R.match(I->getOperand(1));
}
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V))
return (CE->getOpcode() == Instruction::LShr ||
CE->getOpcode() == Instruction::AShr) &&
L.match(CE->getOperand(0)) &&
R.match(CE->getOperand(1));
return false;
}
};
template<typename LHS, typename RHS>
inline Shr_match<LHS, RHS> m_Shr(const LHS &L, const RHS &R) {
return Shr_match<LHS, RHS>(L, R);
}
//===----------------------------------------------------------------------===//

View File

@ -784,7 +784,8 @@ void Andersens::visitInstruction(Instruction &I) {
case Instruction::Unreachable:
case Instruction::Free:
case Instruction::Shl:
case Instruction::Shr:
case Instruction::LShr:
case Instruction::AShr:
return;
default:
// Is this something we aren't handling yet?

View File

@ -280,7 +280,9 @@ call { RET_TOK(OtherOpVal, Call, CALL); }
cast { RET_TOK(OtherOpVal, Cast, CAST); }
select { RET_TOK(OtherOpVal, Select, SELECT); }
shl { RET_TOK(OtherOpVal, Shl, SHL); }
shr { RET_TOK(OtherOpVal, Shr, SHR); }
shr { RET_TOK_OBSOLETE(OtherOpVal, LShr, LSHR); }
lshr { RET_TOK(OtherOpVal, LShr, LSHR); }
ashr { RET_TOK(OtherOpVal, AShr, ASHR); }
vanext { return VANEXT_old; }
vaarg { return VAARG_old; }
va_arg { RET_TOK(OtherOpVal, VAArg , VAARG); }

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,266 @@
typedef union {
/* A Bison parser, made by GNU Bison 2.1. */
/* Skeleton parser for Yacc-like parsing with Bison,
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA. */
/* As a special exception, when this file is copied by Bison into a
Bison output file, you may use that output file without restriction.
This special exception was added by the Free Software Foundation
in version 1.24 of Bison. */
/* Tokens. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
/* Put the tokens into the symbol table, so that GDB and other debuggers
know about them. */
enum yytokentype {
ESINT64VAL = 258,
EUINT64VAL = 259,
SINTVAL = 260,
UINTVAL = 261,
FPVAL = 262,
VOID = 263,
BOOL = 264,
SBYTE = 265,
UBYTE = 266,
SHORT = 267,
USHORT = 268,
INT = 269,
UINT = 270,
LONG = 271,
ULONG = 272,
FLOAT = 273,
DOUBLE = 274,
TYPE = 275,
LABEL = 276,
VAR_ID = 277,
LABELSTR = 278,
STRINGCONSTANT = 279,
IMPLEMENTATION = 280,
ZEROINITIALIZER = 281,
TRUETOK = 282,
FALSETOK = 283,
BEGINTOK = 284,
ENDTOK = 285,
DECLARE = 286,
GLOBAL = 287,
CONSTANT = 288,
SECTION = 289,
VOLATILE = 290,
TO = 291,
DOTDOTDOT = 292,
NULL_TOK = 293,
UNDEF = 294,
CONST = 295,
INTERNAL = 296,
LINKONCE = 297,
WEAK = 298,
APPENDING = 299,
DLLIMPORT = 300,
DLLEXPORT = 301,
EXTERN_WEAK = 302,
OPAQUE = 303,
NOT = 304,
EXTERNAL = 305,
TARGET = 306,
TRIPLE = 307,
ENDIAN = 308,
POINTERSIZE = 309,
LITTLE = 310,
BIG = 311,
ALIGN = 312,
DEPLIBS = 313,
CALL = 314,
TAIL = 315,
ASM_TOK = 316,
MODULE = 317,
SIDEEFFECT = 318,
CC_TOK = 319,
CCC_TOK = 320,
CSRETCC_TOK = 321,
FASTCC_TOK = 322,
COLDCC_TOK = 323,
X86_STDCALLCC_TOK = 324,
X86_FASTCALLCC_TOK = 325,
DATALAYOUT = 326,
RET = 327,
BR = 328,
SWITCH = 329,
INVOKE = 330,
UNWIND = 331,
UNREACHABLE = 332,
ADD = 333,
SUB = 334,
MUL = 335,
UDIV = 336,
SDIV = 337,
FDIV = 338,
UREM = 339,
SREM = 340,
FREM = 341,
AND = 342,
OR = 343,
XOR = 344,
SETLE = 345,
SETGE = 346,
SETLT = 347,
SETGT = 348,
SETEQ = 349,
SETNE = 350,
MALLOC = 351,
ALLOCA = 352,
FREE = 353,
LOAD = 354,
STORE = 355,
GETELEMENTPTR = 356,
PHI_TOK = 357,
CAST = 358,
SELECT = 359,
SHL = 360,
LSHR = 361,
ASHR = 362,
VAARG = 363,
EXTRACTELEMENT = 364,
INSERTELEMENT = 365,
SHUFFLEVECTOR = 366,
VAARG_old = 367,
VANEXT_old = 368
};
#endif
/* Tokens. */
#define ESINT64VAL 258
#define EUINT64VAL 259
#define SINTVAL 260
#define UINTVAL 261
#define FPVAL 262
#define VOID 263
#define BOOL 264
#define SBYTE 265
#define UBYTE 266
#define SHORT 267
#define USHORT 268
#define INT 269
#define UINT 270
#define LONG 271
#define ULONG 272
#define FLOAT 273
#define DOUBLE 274
#define TYPE 275
#define LABEL 276
#define VAR_ID 277
#define LABELSTR 278
#define STRINGCONSTANT 279
#define IMPLEMENTATION 280
#define ZEROINITIALIZER 281
#define TRUETOK 282
#define FALSETOK 283
#define BEGINTOK 284
#define ENDTOK 285
#define DECLARE 286
#define GLOBAL 287
#define CONSTANT 288
#define SECTION 289
#define VOLATILE 290
#define TO 291
#define DOTDOTDOT 292
#define NULL_TOK 293
#define UNDEF 294
#define CONST 295
#define INTERNAL 296
#define LINKONCE 297
#define WEAK 298
#define APPENDING 299
#define DLLIMPORT 300
#define DLLEXPORT 301
#define EXTERN_WEAK 302
#define OPAQUE 303
#define NOT 304
#define EXTERNAL 305
#define TARGET 306
#define TRIPLE 307
#define ENDIAN 308
#define POINTERSIZE 309
#define LITTLE 310
#define BIG 311
#define ALIGN 312
#define DEPLIBS 313
#define CALL 314
#define TAIL 315
#define ASM_TOK 316
#define MODULE 317
#define SIDEEFFECT 318
#define CC_TOK 319
#define CCC_TOK 320
#define CSRETCC_TOK 321
#define FASTCC_TOK 322
#define COLDCC_TOK 323
#define X86_STDCALLCC_TOK 324
#define X86_FASTCALLCC_TOK 325
#define DATALAYOUT 326
#define RET 327
#define BR 328
#define SWITCH 329
#define INVOKE 330
#define UNWIND 331
#define UNREACHABLE 332
#define ADD 333
#define SUB 334
#define MUL 335
#define UDIV 336
#define SDIV 337
#define FDIV 338
#define UREM 339
#define SREM 340
#define FREM 341
#define AND 342
#define OR 343
#define XOR 344
#define SETLE 345
#define SETGE 346
#define SETLT 347
#define SETGT 348
#define SETEQ 349
#define SETNE 350
#define MALLOC 351
#define ALLOCA 352
#define FREE 353
#define LOAD 354
#define STORE 355
#define GETELEMENTPTR 356
#define PHI_TOK 357
#define CAST 358
#define SELECT 359
#define SHL 360
#define LSHR 361
#define ASHR 362
#define VAARG 363
#define EXTRACTELEMENT 364
#define INSERTELEMENT 365
#define SHUFFLEVECTOR 366
#define VAARG_old 367
#define VANEXT_old 368
#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
#line 1040 "/proj/llvm/llvm-3/lib/AsmParser/llvmAsmParser.y"
typedef union YYSTYPE {
llvm::Module *ModuleVal;
llvm::Function *FunctionVal;
std::pair<llvm::PATypeHolder*, char*> *ArgVal;
@ -37,116 +299,14 @@ typedef union {
OtherOpInfo OtherOpVal;
llvm::Module::Endianness Endianness;
} YYSTYPE;
#define ESINT64VAL 257
#define EUINT64VAL 258
#define SINTVAL 259
#define UINTVAL 260
#define FPVAL 261
#define VOID 262
#define BOOL 263
#define SBYTE 264
#define UBYTE 265
#define SHORT 266
#define USHORT 267
#define INT 268
#define UINT 269
#define LONG 270
#define ULONG 271
#define FLOAT 272
#define DOUBLE 273
#define TYPE 274
#define LABEL 275
#define VAR_ID 276
#define LABELSTR 277
#define STRINGCONSTANT 278
#define IMPLEMENTATION 279
#define ZEROINITIALIZER 280
#define TRUETOK 281
#define FALSETOK 282
#define BEGINTOK 283
#define ENDTOK 284
#define DECLARE 285
#define GLOBAL 286
#define CONSTANT 287
#define SECTION 288
#define VOLATILE 289
#define TO 290
#define DOTDOTDOT 291
#define NULL_TOK 292
#define UNDEF 293
#define CONST 294
#define INTERNAL 295
#define LINKONCE 296
#define WEAK 297
#define APPENDING 298
#define DLLIMPORT 299
#define DLLEXPORT 300
#define EXTERN_WEAK 301
#define OPAQUE 302
#define NOT 303
#define EXTERNAL 304
#define TARGET 305
#define TRIPLE 306
#define ENDIAN 307
#define POINTERSIZE 308
#define LITTLE 309
#define BIG 310
#define ALIGN 311
#define DEPLIBS 312
#define CALL 313
#define TAIL 314
#define ASM_TOK 315
#define MODULE 316
#define SIDEEFFECT 317
#define CC_TOK 318
#define CCC_TOK 319
#define CSRETCC_TOK 320
#define FASTCC_TOK 321
#define COLDCC_TOK 322
#define X86_STDCALLCC_TOK 323
#define X86_FASTCALLCC_TOK 324
#define DATALAYOUT 325
#define RET 326
#define BR 327
#define SWITCH 328
#define INVOKE 329
#define UNWIND 330
#define UNREACHABLE 331
#define ADD 332
#define SUB 333
#define MUL 334
#define UDIV 335
#define SDIV 336
#define FDIV 337
#define UREM 338
#define SREM 339
#define FREM 340
#define AND 341
#define OR 342
#define XOR 343
#define SETLE 344
#define SETGE 345
#define SETLT 346
#define SETGT 347
#define SETEQ 348
#define SETNE 349
#define MALLOC 350
#define ALLOCA 351
#define FREE 352
#define LOAD 353
#define STORE 354
#define GETELEMENTPTR 355
#define PHI_TOK 356
#define CAST 357
#define SELECT 358
#define SHL 359
#define SHR 360
#define VAARG 361
#define EXTRACTELEMENT 362
#define INSERTELEMENT 363
#define SHUFFLEVECTOR 364
#define VAARG_old 365
#define VANEXT_old 366
/* Line 1447 of yacc.c. */
#line 304 "llvmAsmParser.tab.h"
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
# define YYSTYPE_IS_TRIVIAL 1
#endif
extern YYSTYPE llvmAsmlval;

View File

@ -820,7 +820,7 @@ static PATypeHolder HandleUpRefs(const Type *ty) {
/// an obsolete opcode. For example, "div" was replaced by [usf]div but we need
/// to maintain backwards compatibility for asm files that still have the "div"
/// instruction. This function handles converting div -> [usf]div appropriately.
/// @brief Convert obsolete opcodes to new values
/// @brief Convert obsolete BinaryOps opcodes to new values
static void
sanitizeOpCode(OpcodeInfo<Instruction::BinaryOps> &OI, const PATypeHolder& PATy)
{
@ -855,7 +855,31 @@ sanitizeOpCode(OpcodeInfo<Instruction::BinaryOps> &OI, const PATypeHolder& PATy)
// Its not obsolete any more, we fixed it.
OI.obsolete = false;
}
/// This function is similar to the previous overload of sanitizeOpCode but
/// operates on Instruction::OtherOps instead of Instruction::BinaryOps.
/// @brief Convert obsolete OtherOps opcodes to new values
static void
sanitizeOpCode(OpcodeInfo<Instruction::OtherOps> &OI, const PATypeHolder& PATy)
{
// If its not obsolete, don't do anything
if (!OI.obsolete)
return;
const Type* Ty = PATy; // type conversion
switch (OI.opcode) {
default:
GenerateError("Invalid obsolete opcode (check Lexer.l)");
break;
case Instruction::LShr:
if (Ty->isSigned())
OI.opcode = Instruction::AShr;
break;
}
// Its not obsolete any more, we fixed it.
OI.obsolete = false;
}
// common code from the two 'RunVMAsmParser' functions
static Module* RunParser(Module * M) {
@ -1126,7 +1150,7 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) {
// Other Operators
%type <OtherOpVal> ShiftOps
%token <OtherOpVal> PHI_TOK CAST SELECT SHL SHR VAARG
%token <OtherOpVal> PHI_TOK CAST SELECT SHL LSHR ASHR VAARG
%token <OtherOpVal> EXTRACTELEMENT INSERTELEMENT SHUFFLEVECTOR
%token VAARG_old VANEXT_old //OBSOLETE
@ -1160,7 +1184,7 @@ ArithmeticOps: ADD | SUB | MUL | UDIV | SDIV | FDIV | UREM | SREM | FREM;
LogicalOps : AND | OR | XOR;
SetCondOps : SETLE | SETGE | SETLT | SETGT | SETEQ | SETNE;
ShiftOps : SHL | SHR;
ShiftOps : SHL | LSHR | ASHR;
// These are some types that allow classification if we only want a particular
// thing... for example, only a signed, unsigned, or integral type.
@ -1730,6 +1754,9 @@ ConstExpr: CAST '(' ConstVal TO Types ')' {
GEN_ERROR("Shift count for shift constant must be unsigned byte!");
if (!$3->getType()->isInteger())
GEN_ERROR("Shift constant expression requires integer operand!");
// Handle opcode upgrade situations
sanitizeOpCode($1, $3->getType());
CHECK_FOR_ERROR;
$$ = ConstantExpr::get($1.opcode, $3, $5);
CHECK_FOR_ERROR
}
@ -2534,6 +2561,9 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
GEN_ERROR("Shift amount must be ubyte!");
if (!$2->getType()->isInteger())
GEN_ERROR("Shift constant expression requires integer operand!");
// Handle opcode upgrade situations
sanitizeOpCode($1, $2->getType());
CHECK_FOR_ERROR;
$$ = new ShiftInst($1.opcode, $2, $4);
CHECK_FOR_ERROR
}

View File

@ -820,7 +820,7 @@ static PATypeHolder HandleUpRefs(const Type *ty) {
/// an obsolete opcode. For example, "div" was replaced by [usf]div but we need
/// to maintain backwards compatibility for asm files that still have the "div"
/// instruction. This function handles converting div -> [usf]div appropriately.
/// @brief Convert obsolete opcodes to new values
/// @brief Convert obsolete BinaryOps opcodes to new values
static void
sanitizeOpCode(OpcodeInfo<Instruction::BinaryOps> &OI, const PATypeHolder& PATy)
{
@ -855,7 +855,31 @@ sanitizeOpCode(OpcodeInfo<Instruction::BinaryOps> &OI, const PATypeHolder& PATy)
// Its not obsolete any more, we fixed it.
OI.obsolete = false;
}
/// This function is similar to the previous overload of sanitizeOpCode but
/// operates on Instruction::OtherOps instead of Instruction::BinaryOps.
/// @brief Convert obsolete OtherOps opcodes to new values
static void
sanitizeOpCode(OpcodeInfo<Instruction::OtherOps> &OI, const PATypeHolder& PATy)
{
// If its not obsolete, don't do anything
if (!OI.obsolete)
return;
const Type* Ty = PATy; // type conversion
switch (OI.opcode) {
default:
GenerateError("Invalid obsolete opcode (check Lexer.l)");
break;
case Instruction::LShr:
if (Ty->isSigned())
OI.opcode = Instruction::AShr;
break;
}
// Its not obsolete any more, we fixed it.
OI.obsolete = false;
}
// common code from the two 'RunVMAsmParser' functions
static Module* RunParser(Module * M) {
@ -1126,7 +1150,7 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) {
// Other Operators
%type <OtherOpVal> ShiftOps
%token <OtherOpVal> PHI_TOK CAST SELECT SHL SHR VAARG
%token <OtherOpVal> PHI_TOK CAST SELECT SHL LSHR ASHR VAARG
%token <OtherOpVal> EXTRACTELEMENT INSERTELEMENT SHUFFLEVECTOR
%token VAARG_old VANEXT_old //OBSOLETE
@ -1160,7 +1184,7 @@ ArithmeticOps: ADD | SUB | MUL | UDIV | SDIV | FDIV | UREM | SREM | FREM;
LogicalOps : AND | OR | XOR;
SetCondOps : SETLE | SETGE | SETLT | SETGT | SETEQ | SETNE;
ShiftOps : SHL | SHR;
ShiftOps : SHL | LSHR | ASHR;
// These are some types that allow classification if we only want a particular
// thing... for example, only a signed, unsigned, or integral type.
@ -1730,6 +1754,9 @@ ConstExpr: CAST '(' ConstVal TO Types ')' {
GEN_ERROR("Shift count for shift constant must be unsigned byte!");
if (!$3->getType()->isInteger())
GEN_ERROR("Shift constant expression requires integer operand!");
// Handle opcode upgrade situations
sanitizeOpCode($1, $3->getType());
CHECK_FOR_ERROR;
$$ = ConstantExpr::get($1.opcode, $3, $5);
CHECK_FOR_ERROR
}
@ -2534,6 +2561,9 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
GEN_ERROR("Shift amount must be ubyte!");
if (!$2->getType()->isInteger())
GEN_ERROR("Shift constant expression requires integer operand!");
// Handle opcode upgrade situations
sanitizeOpCode($1, $2->getType());
CHECK_FOR_ERROR;
$$ = new ShiftInst($1.opcode, $2, $4);
CHECK_FOR_ERROR
}

View File

@ -719,7 +719,15 @@ BytecodeReader::handleObsoleteOpcodes(
Opcode = Instruction::Shl;
break;
case 31: // Shr
Opcode = Instruction::Shr;
// The type of the instruction is based on the operands. We need to
// select ashr or lshr based on that type. The iType values are hardcoded
// to the values used in bytecode version 5 (and prior) because it is
// likely these codes will change in future versions of LLVM. This if
// statement says "if (integer type and signed)"
if (iType >= 2 && iType <= 9 && iType % 2 != 0)
Opcode = Instruction::AShr;
else
Opcode = Instruction::LShr;
break;
case 32: { //VANext_old ( <= llvm 1.5 )
const Type* ArgTy = getValue(iType, Oprnds[0])->getType();
@ -987,7 +995,8 @@ void BytecodeReader::ParseInstruction(std::vector<unsigned> &Oprnds,
}
case Instruction::Shl:
case Instruction::Shr:
case Instruction::LShr:
case Instruction::AShr:
Result = new ShiftInst(Instruction::OtherOps(Opcode),
getValue(iType, Oprnds[0]),
getValue(Type::UByteTyID, Oprnds[1]));
@ -1707,7 +1716,10 @@ inline unsigned fixCEOpcodes(
Opcode = Instruction::Shl;
break;
case 31: // Shr
Opcode = Instruction::Shr;
if (ArgVec[0]->getType()->isSigned())
Opcode = Instruction::AShr;
else
Opcode = Instruction::LShr;
break;
case 34: // Select
Opcode = Instruction::Select;

View File

@ -138,12 +138,6 @@ void DefaultIntrinsicLowering::AddPrototypes(Module &M) {
static Value *LowerBSWAP(Value *V, Instruction *IP) {
assert(V->getType()->isInteger() && "Can't bswap a non-integer type!");
const Type *DestTy = V->getType();
// Force to unsigned so that the shift rights are logical.
if (DestTy->isSigned())
V = new CastInst(V, DestTy->getUnsignedVersion(), V->getName(), IP);
unsigned BitSize = V->getType()->getPrimitiveSizeInBits();
switch(BitSize) {
@ -151,7 +145,7 @@ static Value *LowerBSWAP(Value *V, Instruction *IP) {
case 16: {
Value *Tmp1 = new ShiftInst(Instruction::Shl, V,
ConstantInt::get(Type::UByteTy,8),"bswap.2",IP);
Value *Tmp2 = new ShiftInst(Instruction::Shr, V,
Value *Tmp2 = new ShiftInst(Instruction::LShr, V,
ConstantInt::get(Type::UByteTy,8),"bswap.1",IP);
V = BinaryOperator::createOr(Tmp1, Tmp2, "bswap.i16", IP);
break;
@ -160,10 +154,10 @@ static Value *LowerBSWAP(Value *V, Instruction *IP) {
Value *Tmp4 = new ShiftInst(Instruction::Shl, V,
ConstantInt::get(Type::UByteTy,24),"bswap.4", IP);
Value *Tmp3 = new ShiftInst(Instruction::Shl, V,
ConstantInt::get(Type::UByteTy,8),"bswap.3",IP);
Value *Tmp2 = new ShiftInst(Instruction::Shr, V,
ConstantInt::get(Type::UByteTy,8),"bswap.2",IP);
Value *Tmp1 = new ShiftInst(Instruction::Shr, V,
ConstantInt::get(Type::UByteTy,8),"bswap.3",IP);
Value *Tmp2 = new ShiftInst(Instruction::LShr, V,
ConstantInt::get(Type::UByteTy,8),"bswap.2",IP);
Value *Tmp1 = new ShiftInst(Instruction::LShr, V,
ConstantInt::get(Type::UByteTy,24),"bswap.1", IP);
Tmp3 = BinaryOperator::createAnd(Tmp3,
ConstantInt::get(Type::UIntTy, 0xFF0000),
@ -184,14 +178,14 @@ static Value *LowerBSWAP(Value *V, Instruction *IP) {
Value *Tmp6 = new ShiftInst(Instruction::Shl, V,
ConstantInt::get(Type::UByteTy,24),"bswap.6", IP);
Value *Tmp5 = new ShiftInst(Instruction::Shl, V,
ConstantInt::get(Type::UByteTy,8),"bswap.5",IP);
Value *Tmp4 = new ShiftInst(Instruction::Shr, V,
ConstantInt::get(Type::UByteTy,8),"bswap.4",IP);
Value *Tmp3 = new ShiftInst(Instruction::Shr, V,
ConstantInt::get(Type::UByteTy,8),"bswap.5", IP);
Value* Tmp4 = new ShiftInst(Instruction::LShr, V,
ConstantInt::get(Type::UByteTy,8),"bswap.4", IP);
Value* Tmp3 = new ShiftInst(Instruction::LShr, V,
ConstantInt::get(Type::UByteTy,24),"bswap.3", IP);
Value *Tmp2 = new ShiftInst(Instruction::Shr, V,
Value* Tmp2 = new ShiftInst(Instruction::LShr, V,
ConstantInt::get(Type::UByteTy,40),"bswap.2", IP);
Value *Tmp1 = new ShiftInst(Instruction::Shr, V,
Value* Tmp1 = new ShiftInst(Instruction::LShr, V,
ConstantInt::get(Type::UByteTy,56),"bswap.1", IP);
Tmp7 = BinaryOperator::createAnd(Tmp7,
ConstantInt::get(Type::ULongTy,
@ -222,9 +216,6 @@ static Value *LowerBSWAP(Value *V, Instruction *IP) {
break;
}
}
if (V->getType() != DestTy)
V = new CastInst(V, DestTy, V->getName(), IP);
return V;
}
@ -239,48 +230,33 @@ static Value *LowerCTPOP(Value *V, Instruction *IP) {
0x0000FFFF0000FFFFULL, 0x00000000FFFFFFFFULL
};
const Type *DestTy = V->getType();
// Force to unsigned so that the shift rights are logical.
if (DestTy->isSigned())
V = new CastInst(V, DestTy->getUnsignedVersion(), V->getName(), IP);
unsigned BitSize = V->getType()->getPrimitiveSizeInBits();
for (unsigned i = 1, ct = 0; i != BitSize; i <<= 1, ++ct) {
Value *MaskCst =
ConstantExpr::getCast(ConstantInt::get(Type::ULongTy, MaskValues[ct]),
V->getType());
Value *LHS = BinaryOperator::createAnd(V, MaskCst, "cppop.and1", IP);
Value *VShift = new ShiftInst(Instruction::Shr, V,
Value *VShift = new ShiftInst(Instruction::LShr, V,
ConstantInt::get(Type::UByteTy, i), "ctpop.sh", IP);
Value *RHS = BinaryOperator::createAnd(VShift, MaskCst, "cppop.and2", IP);
V = BinaryOperator::createAdd(LHS, RHS, "ctpop.step", IP);
}
if (V->getType() != DestTy)
V = new CastInst(V, DestTy, V->getName(), IP);
return V;
}
/// LowerCTLZ - Emit the code to lower ctlz of V before the specified
/// instruction IP.
static Value *LowerCTLZ(Value *V, Instruction *IP) {
const Type *DestTy = V->getType();
// Force to unsigned so that the shift rights are logical.
if (DestTy->isSigned())
V = new CastInst(V, DestTy->getUnsignedVersion(), V->getName(), IP);
unsigned BitSize = V->getType()->getPrimitiveSizeInBits();
for (unsigned i = 1; i != BitSize; i <<= 1) {
Value *ShVal = ConstantInt::get(Type::UByteTy, i);
ShVal = new ShiftInst(Instruction::Shr, V, ShVal, "ctlz.sh", IP);
ShVal = new ShiftInst(Instruction::LShr, V, ShVal, "ctlz.sh", IP);
V = BinaryOperator::createOr(V, ShVal, "ctlz.step", IP);
}
if (V->getType() != DestTy)
V = new CastInst(V, DestTy, V->getName(), IP);
V = BinaryOperator::createNot(V, "", IP);
return LowerCTPOP(V, IP);
}

View File

@ -538,10 +538,8 @@ public:
void visitOr (User &I) { visitIntBinary(I, ISD::OR, ISD::VOR); }
void visitXor(User &I) { visitIntBinary(I, ISD::XOR, ISD::VXOR); }
void visitShl(User &I) { visitShift(I, ISD::SHL); }
void visitShr(User &I) {
visitShift(I, I.getType()->isUnsigned() ? ISD::SRL : ISD::SRA);
}
void visitLShr(User &I) { visitShift(I, ISD::SRL); }
void visitAShr(User &I) { visitShift(I, ISD::SRA); }
void visitSetCC(User &I, ISD::CondCode SignedOpc, ISD::CondCode UnsignedOpc,
ISD::CondCode FPOpc);
void visitSetEQ(User &I) { visitSetCC(I, ISD::SETEQ, ISD::SETEQ,

View File

@ -72,8 +72,10 @@ static GenericValue executeSetGEInst(GenericValue Src1, GenericValue Src2,
const Type *Ty);
static GenericValue executeShlInst(GenericValue Src1, GenericValue Src2,
const Type *Ty);
static GenericValue executeShrInst(GenericValue Src1, GenericValue Src2,
const Type *Ty);
static GenericValue executeLShrInst(GenericValue Src1, GenericValue Src2,
const Type *Ty);
static GenericValue executeAShrInst(GenericValue Src1, GenericValue Src2,
const Type *Ty);
static GenericValue executeSelectInst(GenericValue Src1, GenericValue Src2,
GenericValue Src3);
@ -161,10 +163,14 @@ GenericValue Interpreter::getConstantExprValue (ConstantExpr *CE,
return executeShlInst(getOperandValue(CE->getOperand(0), SF),
getOperandValue(CE->getOperand(1), SF),
CE->getOperand(0)->getType());
case Instruction::Shr:
return executeShrInst(getOperandValue(CE->getOperand(0), SF),
getOperandValue(CE->getOperand(1), SF),
CE->getOperand(0)->getType());
case Instruction::LShr:
return executeLShrInst(getOperandValue(CE->getOperand(0), SF),
getOperandValue(CE->getOperand(1), SF),
CE->getOperand(0)->getType());
case Instruction::AShr:
return executeAShrInst(getOperandValue(CE->getOperand(0), SF),
getOperandValue(CE->getOperand(1), SF),
CE->getOperand(0)->getType());
case Instruction::Select:
return executeSelectInst(getOperandValue(CE->getOperand(0), SF),
getOperandValue(CE->getOperand(1), SF),
@ -943,6 +949,10 @@ void Interpreter::visitCallSite(CallSite CS) {
#define IMPLEMENT_SHIFT(OP, TY) \
case Type::TY##TyID: Dest.TY##Val = Src1.TY##Val OP Src2.UByteVal; break
#define IMPLEMENT_SIGNLESS_SHIFT(OP, TY1, TY2) \
case Type::TY2##TyID: \
IMPLEMENT_SHIFT(OP, TY1)
static GenericValue executeShlInst(GenericValue Src1, GenericValue Src2,
const Type *Ty) {
GenericValue Dest;
@ -961,20 +971,31 @@ static GenericValue executeShlInst(GenericValue Src1, GenericValue Src2,
return Dest;
}
static GenericValue executeShrInst(GenericValue Src1, GenericValue Src2,
const Type *Ty) {
static GenericValue executeLShrInst(GenericValue Src1, GenericValue Src2,
const Type *Ty) {
GenericValue Dest;
switch (Ty->getTypeID()) {
IMPLEMENT_SHIFT(>>, UByte);
IMPLEMENT_SHIFT(>>, SByte);
IMPLEMENT_SHIFT(>>, UShort);
IMPLEMENT_SHIFT(>>, Short);
IMPLEMENT_SHIFT(>>, UInt);
IMPLEMENT_SHIFT(>>, Int);
IMPLEMENT_SHIFT(>>, ULong);
IMPLEMENT_SHIFT(>>, Long);
IMPLEMENT_SIGNLESS_SHIFT(>>, UByte, SByte);
IMPLEMENT_SIGNLESS_SHIFT(>>, UShort, Short);
IMPLEMENT_SIGNLESS_SHIFT(>>, UInt, Int);
IMPLEMENT_SIGNLESS_SHIFT(>>, ULong, Long);
default:
std::cout << "Unhandled type for Shr instruction: " << *Ty << "\n";
std::cout << "Unhandled type for LShr instruction: " << *Ty << "\n";
abort();
}
return Dest;
}
static GenericValue executeAShrInst(GenericValue Src1, GenericValue Src2,
const Type *Ty) {
GenericValue Dest;
switch (Ty->getTypeID()) {
IMPLEMENT_SIGNLESS_SHIFT(>>, SByte, UByte);
IMPLEMENT_SIGNLESS_SHIFT(>>, Short, UShort);
IMPLEMENT_SIGNLESS_SHIFT(>>, Int, UInt);
IMPLEMENT_SIGNLESS_SHIFT(>>, Long, ULong);
default:
std::cout << "Unhandled type for AShr instruction: " << *Ty << "\n";
abort();
}
return Dest;
@ -990,13 +1011,23 @@ void Interpreter::visitShl(ShiftInst &I) {
SetValue(&I, Dest, SF);
}
void Interpreter::visitShr(ShiftInst &I) {
void Interpreter::visitLShr(ShiftInst &I) {
ExecutionContext &SF = ECStack.back();
const Type *Ty = I.getOperand(0)->getType();
GenericValue Src1 = getOperandValue(I.getOperand(0), SF);
GenericValue Src2 = getOperandValue(I.getOperand(1), SF);
GenericValue Dest;
Dest = executeShrInst (Src1, Src2, Ty);
Dest = executeLShrInst (Src1, Src2, Ty);
SetValue(&I, Dest, SF);
}
void Interpreter::visitAShr(ShiftInst &I) {
ExecutionContext &SF = ECStack.back();
const Type *Ty = I.getOperand(0)->getType();
GenericValue Src1 = getOperandValue(I.getOperand(0), SF);
GenericValue Src2 = getOperandValue(I.getOperand(1), SF);
GenericValue Dest;
Dest = executeAShrInst (Src1, Src2, Ty);
SetValue(&I, Dest, SF);
}

View File

@ -154,7 +154,8 @@ public:
void visitUnreachableInst(UnreachableInst &I);
void visitShl(ShiftInst &I);
void visitShr(ShiftInst &I);
void visitLShr(ShiftInst &I);
void visitAShr(ShiftInst &I);
void visitVAArgInst(VAArgInst &I);
void visitInstruction(Instruction &I) {
std::cerr << I;

View File

@ -606,7 +606,8 @@ void CWriter::printConstant(Constant *CPV) {
case Instruction::SetGT:
case Instruction::SetGE:
case Instruction::Shl:
case Instruction::Shr:
case Instruction::LShr:
case Instruction::AShr:
{
Out << '(';
bool NeedsClosingParens = printConstExprCast(CE);
@ -631,7 +632,8 @@ void CWriter::printConstant(Constant *CPV) {
case Instruction::SetGT: Out << " > "; break;
case Instruction::SetGE: Out << " >= "; break;
case Instruction::Shl: Out << " << "; break;
case Instruction::Shr: Out << " >> "; break;
case Instruction::LShr:
case Instruction::AShr: Out << " >> "; break;
default: assert(0 && "Illegal opcode here!");
}
printConstantWithCast(CE->getOperand(1), CE->getOpcode());
@ -826,23 +828,23 @@ void CWriter::printConstant(Constant *CPV) {
// because their operands were casted to the expected type. This function takes
// care of detecting that case and printing the cast for the ConstantExpr.
bool CWriter::printConstExprCast(const ConstantExpr* CE) {
bool Result = false;
bool NeedsExplicitCast = false;
const Type* Ty = CE->getOperand(0)->getType();
switch (CE->getOpcode()) {
case Instruction::UDiv:
case Instruction::LShr:
case Instruction::URem:
Result = Ty->isSigned(); break;
case Instruction::SDiv:
case Instruction::UDiv: NeedsExplicitCast = Ty->isSigned(); break;
case Instruction::AShr:
case Instruction::SRem:
Result = Ty->isUnsigned(); break;
case Instruction::SDiv: NeedsExplicitCast = Ty->isUnsigned(); break;
default: break;
}
if (Result) {
if (NeedsExplicitCast) {
Out << "((";
printType(Out, Ty);
Out << ")(";
}
return Result;
return NeedsExplicitCast;
}
// Print a constant assuming that it is the operand for a given Opcode. The
@ -863,6 +865,7 @@ void CWriter::printConstantWithCast(Constant* CPV, unsigned Opcode) {
default:
// for most instructions, it doesn't matter
break;
case Instruction::LShr:
case Instruction::UDiv:
case Instruction::URem:
// For UDiv/URem get correct type
@ -871,6 +874,7 @@ void CWriter::printConstantWithCast(Constant* CPV, unsigned Opcode) {
shouldCast = true;
}
break;
case Instruction::AShr:
case Instruction::SDiv:
case Instruction::SRem:
// For SDiv/SRem get correct type
@ -927,23 +931,23 @@ void CWriter::writeOperand(Value *Operand) {
// This function takes care of detecting that case and printing the cast
// for the Instruction.
bool CWriter::writeInstructionCast(const Instruction &I) {
bool Result = false;
bool NeedsExplicitCast = false;
const Type* Ty = I.getOperand(0)->getType();
switch (I.getOpcode()) {
case Instruction::UDiv:
case Instruction::LShr:
case Instruction::URem:
Result = Ty->isSigned(); break;
case Instruction::SDiv:
case Instruction::UDiv: NeedsExplicitCast = Ty->isSigned(); break;
case Instruction::AShr:
case Instruction::SRem:
Result = Ty->isUnsigned(); break;
case Instruction::SDiv: NeedsExplicitCast = Ty->isUnsigned(); break;
default: break;
}
if (Result) {
if (NeedsExplicitCast) {
Out << "((";
printType(Out, Ty);
Out << ")(";
}
return Result;
return NeedsExplicitCast;
}
// Write the operand with a cast to another type based on the Opcode being used.
@ -964,6 +968,7 @@ void CWriter::writeOperandWithCast(Value* Operand, unsigned Opcode) {
default:
// for most instructions, it doesn't matter
break;
case Instruction::LShr:
case Instruction::UDiv:
case Instruction::URem:
// For UDiv to have unsigned operands
@ -972,6 +977,7 @@ void CWriter::writeOperandWithCast(Value* Operand, unsigned Opcode) {
shouldCast = true;
}
break;
case Instruction::AShr:
case Instruction::SDiv:
case Instruction::SRem:
if (OpTy->isUnsigned()) {
@ -1832,7 +1838,8 @@ void CWriter::visitBinaryOperator(Instruction &I) {
case Instruction::SetLT: Out << " < "; break;
case Instruction::SetGT: Out << " > "; break;
case Instruction::Shl : Out << " << "; break;
case Instruction::Shr : Out << " >> "; break;
case Instruction::LShr:
case Instruction::AShr: Out << " >> "; break;
default: std::cerr << "Invalid operator type!" << I; abort();
}

View File

@ -76,10 +76,12 @@ bool llvm::ExpressionConvertibleToType(Value *V, const Type *Ty,
!ExpressionConvertibleToType(I->getOperand(1), Ty, CTMap, TD))
return false;
break;
case Instruction::Shr:
case Instruction::LShr:
case Instruction::AShr:
if (!Ty->isInteger()) return false;
if (Ty->isSigned() != V->getType()->isSigned()) return false;
// FALL THROUGH
if (!ExpressionConvertibleToType(I->getOperand(0), Ty, CTMap, TD))
return false;
break;
case Instruction::Shl:
if (!Ty->isInteger()) return false;
if (!ExpressionConvertibleToType(I->getOperand(0), Ty, CTMap, TD))
@ -243,7 +245,8 @@ Value *llvm::ConvertExpressionToType(Value *V, const Type *Ty,
break;
case Instruction::Shl:
case Instruction::Shr:
case Instruction::LShr:
case Instruction::AShr:
Res = new ShiftInst(cast<ShiftInst>(I)->getOpcode(), Dummy,
I->getOperand(1), Name);
VMC.ExprMap[I] = Res;
@ -476,7 +479,8 @@ static bool OperandConvertibleToType(User *U, Value *V, const Type *Ty,
Value *OtherOp = I->getOperand((V == I->getOperand(0)) ? 1 : 0);
return ExpressionConvertibleToType(OtherOp, Ty, CTMap, TD);
}
case Instruction::Shr:
case Instruction::LShr:
case Instruction::AShr:
if (Ty->isSigned() != V->getType()->isSigned()) return false;
// FALL THROUGH
case Instruction::Shl:
@ -746,7 +750,8 @@ static void ConvertOperandToType(User *U, Value *OldVal, Value *NewVal,
break;
}
case Instruction::Shl:
case Instruction::Shr:
case Instruction::LShr:
case Instruction::AShr:
assert(I->getOperand(0) == OldVal);
Res = new ShiftInst(cast<ShiftInst>(I)->getOpcode(), NewVal,
I->getOperand(1), Name);

View File

@ -731,7 +731,7 @@ static void ComputeMaskedBits(Value *V, uint64_t Mask, uint64_t &KnownZero,
return;
}
break;
case Instruction::Shr:
case Instruction::LShr:
// (ushr X, C1) & C2 == 0 iff (-1 >> C1) & C2 == 0
if (ConstantInt *SA = dyn_cast<ConstantInt>(I->getOperand(1))) {
// Compute the new bits that are at the top now.
@ -739,29 +739,39 @@ static void ComputeMaskedBits(Value *V, uint64_t Mask, uint64_t &KnownZero,
uint64_t HighBits = (1ULL << ShiftAmt)-1;
HighBits <<= I->getType()->getPrimitiveSizeInBits()-ShiftAmt;
if (I->getType()->isUnsigned()) { // Unsigned shift right.
Mask <<= ShiftAmt;
ComputeMaskedBits(I->getOperand(0), Mask, KnownZero,KnownOne,Depth+1);
assert((KnownZero & KnownOne) == 0&&"Bits known to be one AND zero?");
KnownZero >>= ShiftAmt;
KnownOne >>= ShiftAmt;
KnownZero |= HighBits; // high bits known zero.
} else {
Mask <<= ShiftAmt;
ComputeMaskedBits(I->getOperand(0), Mask, KnownZero,KnownOne,Depth+1);
assert((KnownZero & KnownOne) == 0&&"Bits known to be one AND zero?");
KnownZero >>= ShiftAmt;
KnownOne >>= ShiftAmt;
// Unsigned shift right.
Mask <<= ShiftAmt;
ComputeMaskedBits(I->getOperand(0), Mask, KnownZero,KnownOne,Depth+1);
assert((KnownZero & KnownOne) == 0&&"Bits known to be one AND zero?");
KnownZero >>= ShiftAmt;
KnownOne >>= ShiftAmt;
KnownZero |= HighBits; // high bits known zero.
return;
}
break;
case Instruction::AShr:
// (ushr X, C1) & C2 == 0 iff (-1 >> C1) & C2 == 0
if (ConstantInt *SA = dyn_cast<ConstantInt>(I->getOperand(1))) {
// Compute the new bits that are at the top now.
uint64_t ShiftAmt = SA->getZExtValue();
uint64_t HighBits = (1ULL << ShiftAmt)-1;
HighBits <<= I->getType()->getPrimitiveSizeInBits()-ShiftAmt;
// Signed shift right.
Mask <<= ShiftAmt;
ComputeMaskedBits(I->getOperand(0), Mask, KnownZero,KnownOne,Depth+1);
assert((KnownZero & KnownOne) == 0&&"Bits known to be one AND zero?");
KnownZero >>= ShiftAmt;
KnownOne >>= ShiftAmt;
// Handle the sign bits.
uint64_t SignBit = 1ULL << (I->getType()->getPrimitiveSizeInBits()-1);
SignBit >>= ShiftAmt; // Adjust to where it is now in the mask.
// Handle the sign bits.
uint64_t SignBit = 1ULL << (I->getType()->getPrimitiveSizeInBits()-1);
SignBit >>= ShiftAmt; // Adjust to where it is now in the mask.
if (KnownZero & SignBit) { // New bits are known zero.
KnownZero |= HighBits;
} else if (KnownOne & SignBit) { // New bits are known one.
KnownOne |= HighBits;
}
if (KnownZero & SignBit) { // New bits are known zero.
KnownZero |= HighBits;
} else if (KnownOne & SignBit) { // New bits are known one.
KnownOne |= HighBits;
}
return;
}
@ -1119,21 +1129,37 @@ bool InstCombiner::SimplifyDemandedBits(Value *V, uint64_t DemandedMask,
KnownZero |= (1ULL << ShiftAmt) - 1; // low bits known zero.
}
break;
case Instruction::Shr:
case Instruction::LShr:
// For a logical shift right
if (ConstantInt *SA = dyn_cast<ConstantInt>(I->getOperand(1))) {
unsigned ShiftAmt = SA->getZExtValue();
// Compute the new bits that are at the top now.
uint64_t HighBits = (1ULL << ShiftAmt)-1;
HighBits <<= I->getType()->getPrimitiveSizeInBits() - ShiftAmt;
uint64_t TypeMask = I->getType()->getIntegralTypeMask();
// Unsigned shift right.
if (SimplifyDemandedBits(I->getOperand(0),
(DemandedMask << ShiftAmt) & TypeMask,
KnownZero, KnownOne, Depth+1))
return true;
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
KnownZero &= TypeMask;
KnownOne &= TypeMask;
KnownZero >>= ShiftAmt;
KnownOne >>= ShiftAmt;
KnownZero |= HighBits; // high bits known zero.
}
break;
case Instruction::AShr:
// If this is an arithmetic shift right and only the low-bit is set, we can
// always convert this into a logical shr, even if the shift amount is
// variable. The low bit of the shift cannot be an input sign bit unless
// the shift amount is >= the size of the datatype, which is undefined.
if (DemandedMask == 1 && I->getType()->isSigned()) {
// Convert the input to unsigned.
Value *NewVal = InsertCastBefore(I->getOperand(0),
I->getType()->getUnsignedVersion(), *I);
// Perform the unsigned shift right.
NewVal = new ShiftInst(Instruction::Shr, NewVal, I->getOperand(1),
I->getName());
InsertNewInstBefore(cast<Instruction>(NewVal), *I);
// Then cast that to the destination type.
NewVal = new CastInst(NewVal, I->getType(), I->getName());
if (DemandedMask == 1) {
// Perform the logical shift right.
Value *NewVal = new ShiftInst(Instruction::LShr, I->getOperand(0),
I->getOperand(1), I->getName());
InsertNewInstBefore(cast<Instruction>(NewVal), *I);
return UpdateValueUsesWith(I, NewVal);
}
@ -1145,48 +1171,31 @@ bool InstCombiner::SimplifyDemandedBits(Value *V, uint64_t DemandedMask,
uint64_t HighBits = (1ULL << ShiftAmt)-1;
HighBits <<= I->getType()->getPrimitiveSizeInBits() - ShiftAmt;
uint64_t TypeMask = I->getType()->getIntegralTypeMask();
if (I->getType()->isUnsigned()) { // Unsigned shift right.
if (SimplifyDemandedBits(I->getOperand(0),
(DemandedMask << ShiftAmt) & TypeMask,
KnownZero, KnownOne, Depth+1))
return true;
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
KnownZero &= TypeMask;
KnownOne &= TypeMask;
KnownZero >>= ShiftAmt;
KnownOne >>= ShiftAmt;
KnownZero |= HighBits; // high bits known zero.
} else { // Signed shift right.
if (SimplifyDemandedBits(I->getOperand(0),
(DemandedMask << ShiftAmt) & TypeMask,
KnownZero, KnownOne, Depth+1))
return true;
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
KnownZero &= TypeMask;
KnownOne &= TypeMask;
KnownZero >>= ShiftAmt;
KnownOne >>= ShiftAmt;
// Signed shift right.
if (SimplifyDemandedBits(I->getOperand(0),
(DemandedMask << ShiftAmt) & TypeMask,
KnownZero, KnownOne, Depth+1))
return true;
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
KnownZero &= TypeMask;
KnownOne &= TypeMask;
KnownZero >>= ShiftAmt;
KnownOne >>= ShiftAmt;
// Handle the sign bits.
uint64_t SignBit = 1ULL << (I->getType()->getPrimitiveSizeInBits()-1);
SignBit >>= ShiftAmt; // Adjust to where it is now in the mask.
// Handle the sign bits.
uint64_t SignBit = 1ULL << (I->getType()->getPrimitiveSizeInBits()-1);
SignBit >>= ShiftAmt; // Adjust to where it is now in the mask.
// If the input sign bit is known to be zero, or if none of the top bits
// are demanded, turn this into an unsigned shift right.
if ((KnownZero & SignBit) || (HighBits & ~DemandedMask) == HighBits) {
// Convert the input to unsigned.
Value *NewVal = InsertCastBefore(I->getOperand(0),
I->getType()->getUnsignedVersion(), *I);
// Perform the unsigned shift right.
NewVal = new ShiftInst(Instruction::Shr, NewVal, SA, I->getName());
InsertNewInstBefore(cast<Instruction>(NewVal), *I);
// Then cast that to the destination type.
NewVal = new CastInst(NewVal, I->getType(), I->getName());
InsertNewInstBefore(cast<Instruction>(NewVal), *I);
return UpdateValueUsesWith(I, NewVal);
} else if (KnownOne & SignBit) { // New bits are known one.
KnownOne |= HighBits;
}
// If the input sign bit is known to be zero, or if none of the top bits
// are demanded, turn this into an unsigned shift right.
if ((KnownZero & SignBit) || (HighBits & ~DemandedMask) == HighBits) {
// Perform the logical shift right.
Value *NewVal = new ShiftInst(Instruction::LShr, I->getOperand(0),
SA, I->getName());
InsertNewInstBefore(cast<Instruction>(NewVal), *I);
return UpdateValueUsesWith(I, NewVal);
} else if (KnownOne & SignBit) { // New bits are known one.
KnownOne |= HighBits;
}
}
break;
@ -1899,29 +1908,28 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) {
if (C->isNullValue()) {
Value *NoopCastedRHS = RemoveNoopCast(Op1);
if (ShiftInst *SI = dyn_cast<ShiftInst>(NoopCastedRHS))
if (SI->getOpcode() == Instruction::Shr)
if (SI->getOpcode() == Instruction::LShr) {
if (ConstantInt *CU = dyn_cast<ConstantInt>(SI->getOperand(1))) {
const Type *NewTy;
if (SI->getType()->isSigned())
NewTy = SI->getType()->getUnsignedVersion();
else
NewTy = SI->getType()->getSignedVersion();
// Check to see if we are shifting out everything but the sign bit.
if (CU->getZExtValue() ==
SI->getType()->getPrimitiveSizeInBits()-1) {
// Ok, the transformation is safe. Insert a cast of the incoming
// value, then the new shift, then the new cast.
Value *InV = InsertCastBefore(SI->getOperand(0), NewTy, I);
Instruction *NewShift = new ShiftInst(Instruction::Shr, InV,
CU, SI->getName());
if (NewShift->getType() == I.getType())
return NewShift;
else {
InsertNewInstBefore(NewShift, I);
return new CastInst(NewShift, I.getType());
}
// Ok, the transformation is safe. Insert AShr.
return new ShiftInst(Instruction::AShr, SI->getOperand(0),
CU, SI->getName());
}
}
}
else if (SI->getOpcode() == Instruction::AShr) {
if (ConstantInt *CU = dyn_cast<ConstantInt>(SI->getOperand(1))) {
// Check to see if we are shifting out everything but the sign bit.
if (CU->getZExtValue() ==
SI->getType()->getPrimitiveSizeInBits()-1) {
// Ok, the transformation is safe. Insert LShr.
return new ShiftInst(Instruction::LShr, SI->getOperand(0),
CU, SI->getName());
}
}
}
}
// Try to fold constant sub into select arguments.
@ -2138,7 +2146,7 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) {
}
Value *V =
InsertNewInstBefore(new ShiftInst(Instruction::Shr, SCIOp0, Amt,
InsertNewInstBefore(new ShiftInst(Instruction::AShr, SCIOp0, Amt,
BoolCast->getOperand(0)->getName()+
".mask"), I);
@ -2262,18 +2270,8 @@ Instruction *InstCombiner::visitUDiv(BinaryOperator &I) {
if (uint64_t Val = C->getZExtValue()) // Don't break X / 0
if (isPowerOf2_64(Val)) {
uint64_t ShiftAmt = Log2_64(Val);
Value* X = Op0;
const Type* XTy = X->getType();
bool isSigned = XTy->isSigned();
if (isSigned)
X = InsertCastBefore(X, XTy->getUnsignedVersion(), I);
Instruction* Result =
new ShiftInst(Instruction::Shr, X,
ConstantInt::get(Type::UByteTy, ShiftAmt));
if (!isSigned)
return Result;
InsertNewInstBefore(Result, I);
return new CastInst(Result, XTy->getSignedVersion(), I.getName());
return new ShiftInst(Instruction::LShr, Op0,
ConstantInt::get(Type::UByteTy, ShiftAmt));
}
}
@ -2285,20 +2283,11 @@ Instruction *InstCombiner::visitUDiv(BinaryOperator &I) {
if (isPowerOf2_64(C1)) {
Value *N = RHSI->getOperand(1);
const Type* NTy = N->getType();
bool isSigned = NTy->isSigned();
if (uint64_t C2 = Log2_64(C1)) {
if (isSigned) {
NTy = NTy->getUnsignedVersion();
N = InsertCastBefore(N, NTy, I);
}
Constant *C2V = ConstantInt::get(NTy, C2);
N = InsertNewInstBefore(BinaryOperator::createAdd(N, C2V, "tmp"), I);
}
Instruction* Result = new ShiftInst(Instruction::Shr, Op0, N);
if (!isSigned)
return Result;
InsertNewInstBefore(Result, I);
return new CastInst(Result, NTy->getSignedVersion(), I.getName());
return new ShiftInst(Instruction::LShr, Op0, N);
}
}
}
@ -2313,31 +2302,20 @@ Instruction *InstCombiner::visitUDiv(BinaryOperator &I) {
if (isPowerOf2_64(TVA) && isPowerOf2_64(FVA)) {
// Compute the shift amounts
unsigned TSA = Log2_64(TVA), FSA = Log2_64(FVA);
// Make sure we get the unsigned version of X
Value* X = Op0;
const Type* origXTy = X->getType();
bool isSigned = origXTy->isSigned();
if (isSigned)
X = InsertCastBefore(X, X->getType()->getUnsignedVersion(), I);
// Construct the "on true" case of the select
Constant *TC = ConstantInt::get(Type::UByteTy, TSA);
Instruction *TSI =
new ShiftInst(Instruction::Shr, X, TC, SI->getName()+".t");
new ShiftInst(Instruction::LShr, Op0, TC, SI->getName()+".t");
TSI = InsertNewInstBefore(TSI, I);
// Construct the "on false" case of the select
Constant *FC = ConstantInt::get(Type::UByteTy, FSA);
Instruction *FSI =
new ShiftInst(Instruction::Shr, X, FC, SI->getName()+".f");
new ShiftInst(Instruction::LShr, Op0, FC, SI->getName()+".f");
FSI = InsertNewInstBefore(FSI, I);
// construct the select instruction and return it.
SelectInst* NewSI =
new SelectInst(SI->getOperand(0), TSI, FSI, SI->getName());
if (!isSigned)
return NewSI;
InsertNewInstBefore(NewSI, I);
return new CastInst(NewSI, origXTy, NewSI->getName());
return new SelectInst(SI->getOperand(0), TSI, FSI, SI->getName());
}
}
}
@ -2807,44 +2785,40 @@ Instruction *InstCombiner::OptAndOp(Instruction *Op,
}
break;
}
case Instruction::Shr:
case Instruction::LShr:
{
// We know that the AND will not produce any of the bits shifted in, so if
// the anded constant includes them, clear them now! This only applies to
// unsigned shifts, because a signed shr may bring in set bits!
//
if (AndRHS->getType()->isUnsigned()) {
Constant *AllOne = ConstantIntegral::getAllOnesValue(AndRHS->getType());
Constant *ShrMask = ConstantExpr::getShr(AllOne, OpRHS);
Constant *CI = ConstantExpr::getAnd(AndRHS, ShrMask);
Constant *AllOne = ConstantIntegral::getAllOnesValue(AndRHS->getType());
Constant *ShrMask = ConstantExpr::getLShr(AllOne, OpRHS);
Constant *CI = ConstantExpr::getAnd(AndRHS, ShrMask);
if (CI == ShrMask) { // Masking out bits that the shift already masks.
return ReplaceInstUsesWith(TheAnd, Op);
} else if (CI != AndRHS) {
TheAnd.setOperand(1, CI); // Reduce bits set in and cst.
return &TheAnd;
}
} else { // Signed shr.
// See if this is shifting in some sign extension, then masking it out
// with an and.
if (Op->hasOneUse()) {
Constant *AllOne = ConstantIntegral::getAllOnesValue(AndRHS->getType());
Constant *ShrMask = ConstantExpr::getUShr(AllOne, OpRHS);
Constant *CI = ConstantExpr::getAnd(AndRHS, ShrMask);
if (CI == AndRHS) { // Masking out bits shifted in.
// Make the argument unsigned.
Value *ShVal = Op->getOperand(0);
ShVal = InsertCastBefore(ShVal,
ShVal->getType()->getUnsignedVersion(),
TheAnd);
ShVal = InsertNewInstBefore(new ShiftInst(Instruction::Shr, ShVal,
OpRHS, Op->getName()),
TheAnd);
Value *AndRHS2 = ConstantExpr::getCast(AndRHS, ShVal->getType());
ShVal = InsertNewInstBefore(BinaryOperator::createAnd(ShVal, AndRHS2,
TheAnd.getName()),
TheAnd);
return new CastInst(ShVal, Op->getType());
}
if (CI == ShrMask) { // Masking out bits that the shift already masks.
return ReplaceInstUsesWith(TheAnd, Op);
} else if (CI != AndRHS) {
TheAnd.setOperand(1, CI); // Reduce bits set in and cst.
return &TheAnd;
}
break;
}
case Instruction::AShr:
// Signed shr.
// See if this is shifting in some sign extension, then masking it out
// with an and.
if (Op->hasOneUse()) {
Constant *AllOne = ConstantIntegral::getAllOnesValue(AndRHS->getType());
Constant *ShrMask = ConstantExpr::getLShr(AllOne, OpRHS);
Constant *CI = ConstantExpr::getAnd(AndRHS, ShrMask);
if (CI == AndRHS) { // Masking out bits shifted in.
// Make the argument unsigned.
Value *ShVal = Op->getOperand(0);
ShVal = InsertNewInstBefore(new ShiftInst(Instruction::LShr, ShVal,
OpRHS, Op->getName()),
TheAnd);
Value *AndRHS2 = ConstantExpr::getCast(AndRHS, ShVal->getType());
return BinaryOperator::createAnd(ShVal, AndRHS2, TheAnd.getName());
}
}
break;
@ -4294,7 +4268,7 @@ Instruction *InstCombiner::visitSetCondInst(SetCondInst &I) {
if (CanFold) {
Constant *NewCst;
if (Shift->getOpcode() == Instruction::Shl)
NewCst = ConstantExpr::getUShr(CI, ShAmt);
NewCst = ConstantExpr::getLShr(CI, ShAmt);
else
NewCst = ConstantExpr::getShl(CI, ShAmt);
@ -4312,7 +4286,7 @@ Instruction *InstCombiner::visitSetCondInst(SetCondInst &I) {
I.setOperand(1, NewCst);
Constant *NewAndCST;
if (Shift->getOpcode() == Instruction::Shl)
NewAndCST = ConstantExpr::getUShr(AndCST, ShAmt);
NewAndCST = ConstantExpr::getLShr(AndCST, ShAmt);
else
NewAndCST = ConstantExpr::getShl(AndCST, ShAmt);
LHSI->setOperand(1, NewAndCST);
@ -4338,7 +4312,7 @@ Instruction *InstCombiner::visitSetCondInst(SetCondInst &I) {
isa<Instruction>(Shift->getOperand(0))) {
// Compute C << Y.
Value *NS;
if (Shift->getOpcode() == Instruction::Shr) {
if (Shift->getOpcode() == Instruction::LShr) {
NS = new ShiftInst(Instruction::Shl, AndCST, Shift->getOperand(1),
"tmp");
} else {
@ -4347,7 +4321,7 @@ Instruction *InstCombiner::visitSetCondInst(SetCondInst &I) {
if (AndCST->getType()->isSigned())
NewAndCST = ConstantExpr::getCast(AndCST,
AndCST->getType()->getUnsignedVersion());
NS = new ShiftInst(Instruction::Shr, NewAndCST,
NS = new ShiftInst(Instruction::LShr, NewAndCST,
Shift->getOperand(1), "tmp");
}
InsertNewInstBefore(cast<Instruction>(NS), I);
@ -4385,7 +4359,7 @@ Instruction *InstCombiner::visitSetCondInst(SetCondInst &I) {
// If we are comparing against bits always shifted out, the
// comparison cannot succeed.
Constant *Comp =
ConstantExpr::getShl(ConstantExpr::getShr(CI, ShAmt), ShAmt);
ConstantExpr::getShl(ConstantExpr::getLShr(CI, ShAmt), ShAmt);
if (Comp != CI) {// Comparing against a bit that we know is zero.
bool IsSetNE = I.getOpcode() == Instruction::SetNE;
Constant *Cst = ConstantBool::get(IsSetNE);
@ -4411,13 +4385,14 @@ Instruction *InstCombiner::visitSetCondInst(SetCondInst &I) {
Mask, LHSI->getName()+".mask");
Value *And = InsertNewInstBefore(AndI, I);
return new SetCondInst(I.getOpcode(), And,
ConstantExpr::getUShr(CI, ShAmt));
ConstantExpr::getLShr(CI, ShAmt));
}
}
}
break;
case Instruction::Shr: // (setcc (shr X, ShAmt), CI)
case Instruction::LShr: // (setcc (shr X, ShAmt), CI)
case Instruction::AShr:
if (ConstantInt *ShAmt = dyn_cast<ConstantInt>(LHSI->getOperand(1))) {
if (I.isEquality()) {
// Check that the shift amount is in range. If not, don't perform
@ -4429,8 +4404,13 @@ Instruction *InstCombiner::visitSetCondInst(SetCondInst &I) {
// If we are comparing against bits always shifted out, the
// comparison cannot succeed.
Constant *Comp =
ConstantExpr::getShr(ConstantExpr::getShl(CI, ShAmt), ShAmt);
Constant *Comp;
if (CI->getType()->isUnsigned())
Comp = ConstantExpr::getLShr(ConstantExpr::getShl(CI, ShAmt),
ShAmt);
else
Comp = ConstantExpr::getAShr(ConstantExpr::getShl(CI, ShAmt),
ShAmt);
if (Comp != CI) {// Comparing against a bit that we know is zero.
bool IsSetNE = I.getOpcode() == Instruction::SetNE;
@ -5019,10 +4999,7 @@ Instruction *InstCombiner::visitShiftInst(ShiftInst &I) {
if (I.isArithmeticShift()) {
if (MaskedValueIsZero(Op0,
1ULL << (I.getType()->getPrimitiveSizeInBits()-1))) {
Value *V = InsertCastBefore(Op0, I.getType()->getUnsignedVersion(), I);
V = InsertNewInstBefore(new ShiftInst(Instruction::Shr, V, Op1,
I.getName()), I);
return new CastInst(V, I.getType());
return new ShiftInst(Instruction::LShr, Op0, Op1, I.getName());
}
}
@ -5036,7 +5013,8 @@ Instruction *InstCombiner::visitShiftInst(ShiftInst &I) {
Instruction *InstCombiner::FoldShiftByConstant(Value *Op0, ConstantInt *Op1,
ShiftInst &I) {
bool isLeftShift = I.getOpcode() == Instruction::Shl;
bool isSignedShift = Op0->getType()->isSigned();
bool isSignedShift = isLeftShift ? Op0->getType()->isSigned() :
I.getOpcode() == Instruction::AShr;
bool isUnsignedShift = !isSignedShift;
// See if we can simplify any instructions used by the instruction whose sole
@ -5229,7 +5207,9 @@ Instruction *InstCombiner::FoldShiftByConstant(Value *Op0, ConstantInt *Op1,
// signedness of the input shift may differ from the current shift if there
// is a noop cast between the two.
bool isShiftOfLeftShift = ShiftOp->getOpcode() == Instruction::Shl;
bool isShiftOfSignedShift = ShiftOp->getType()->isSigned();
bool isShiftOfSignedShift = isShiftOfLeftShift ?
ShiftOp->getType()->isSigned() :
ShiftOp->getOpcode() == Instruction::AShr;
bool isShiftOfUnsignedShift = !isShiftOfSignedShift;
ConstantInt *ShiftAmt1C = cast<ConstantInt>(ShiftOp->getOperand(1));
@ -5252,8 +5232,12 @@ Instruction *InstCombiner::FoldShiftByConstant(Value *Op0, ConstantInt *Op1,
Value *Op = ShiftOp->getOperand(0);
if (isShiftOfSignedShift != isSignedShift)
Op = InsertNewInstBefore(new CastInst(Op, I.getType(), "tmp"), I);
return new ShiftInst(I.getOpcode(), Op,
ShiftInst* ShiftResult = new ShiftInst(I.getOpcode(), Op,
ConstantInt::get(Type::UByteTy, Amt));
if (I.getType() == ShiftResult->getType())
return ShiftResult;
InsertNewInstBefore(ShiftResult, I);
return new CastInst(ShiftResult, I.getType());
}
// Check for (A << c1) >> c2 or (A >> c1) << c2. If we are dealing with
@ -5265,10 +5249,10 @@ Instruction *InstCombiner::FoldShiftByConstant(Value *Op0, ConstantInt *Op1,
if (isLeftShift)
C = ConstantExpr::getShl(C, ShiftAmt1C);
else
C = ConstantExpr::getUShr(C, ShiftAmt1C);
C = ConstantExpr::getLShr(C, ShiftAmt1C);
Value *Op = ShiftOp->getOperand(0);
if (isShiftOfSignedShift != isSignedShift)
if (Op->getType() != C->getType())
Op = InsertCastBefore(Op, I.getType(), I);
Instruction *Mask =
@ -5283,14 +5267,8 @@ Instruction *InstCombiner::FoldShiftByConstant(Value *Op0, ConstantInt *Op1,
ConstantInt::get(Type::UByteTy, ShiftAmt2-ShiftAmt1));
} else if (isShiftOfUnsignedShift || isShiftOfLeftShift) {
if (isShiftOfUnsignedShift && !isShiftOfLeftShift && isSignedShift) {
// Make sure to emit an unsigned shift right, not a signed one.
Mask = InsertNewInstBefore(new CastInst(Mask,
Mask->getType()->getUnsignedVersion(),
Op->getName()), I);
Mask = new ShiftInst(Instruction::Shr, Mask,
ConstantInt::get(Type::UByteTy, ShiftAmt1-ShiftAmt2));
InsertNewInstBefore(Mask, I);
return new CastInst(Mask, I.getType());
return new ShiftInst(Instruction::LShr, Mask,
ConstantInt::get(Type::UByteTy, ShiftAmt1-ShiftAmt2));
} else {
return new ShiftInst(ShiftOp->getOpcode(), Mask,
ConstantInt::get(Type::UByteTy, ShiftAmt1-ShiftAmt2));
@ -5792,7 +5770,7 @@ Instruction *InstCombiner::visitCastInst(CastInst &CI) {
case Instruction::Shl:
// Allow changing the sign of the source operand. Do not allow changing
// the size of the shift, UNLESS the shift amount is a constant. We
// mush not change variable sized shifts to a smaller size, because it
// must not change variable sized shifts to a smaller size, because it
// is undefined to shift more bits out than exist in the value.
if (DestBitSize == SrcBitSize ||
(DestBitSize < SrcBitSize && isa<Constant>(Op1))) {
@ -5800,21 +5778,16 @@ Instruction *InstCombiner::visitCastInst(CastInst &CI) {
return new ShiftInst(Instruction::Shl, Op0c, Op1);
}
break;
case Instruction::Shr:
case Instruction::AShr:
// If this is a signed shr, and if all bits shifted in are about to be
// truncated off, turn it into an unsigned shr to allow greater
// simplifications.
if (DestBitSize < SrcBitSize && Src->getType()->isSigned() &&
if (DestBitSize < SrcBitSize &&
isa<ConstantInt>(Op1)) {
unsigned ShiftAmt = cast<ConstantInt>(Op1)->getZExtValue();
if (SrcBitSize > ShiftAmt && SrcBitSize-ShiftAmt >= DestBitSize) {
// Convert to unsigned.
Value *N1 = InsertOperandCastBefore(Op0,
Op0->getType()->getUnsignedVersion(), &CI);
// Insert the new shift, which is now unsigned.
N1 = InsertNewInstBefore(new ShiftInst(Instruction::Shr, N1,
Op1, Src->getName()), CI);
return new CastInst(N1, CI.getType());
// Insert the new logical shift right.
return new ShiftInst(Instruction::LShr, Op0, Op1);
}
}
break;
@ -5853,13 +5826,9 @@ Instruction *InstCombiner::visitCastInst(CastInst &CI) {
unsigned ShiftAmt = Log2_64(KnownZero^TypeMask);
Value *In = Op0;
if (ShiftAmt) {
// Perform an unsigned shr by shiftamt. Convert input to
// unsigned if it is signed.
if (In->getType()->isSigned())
In = InsertCastBefore(
In, In->getType()->getUnsignedVersion(), CI);
// Perform a logical shr by shiftamt.
// Insert the shift to put the result in the low bit.
In = InsertNewInstBefore(new ShiftInst(Instruction::Shr, In,
In = InsertNewInstBefore(new ShiftInst(Instruction::LShr, In,
ConstantInt::get(Type::UByteTy, ShiftAmt),
In->getName()+".lobit"), CI);
}
@ -5934,7 +5903,8 @@ static unsigned GetSelectFoldableOperands(Instruction *I) {
return 3; // Can fold through either operand.
case Instruction::Sub: // Can only fold on the amount subtracted.
case Instruction::Shl: // Can only fold on the shift amount.
case Instruction::Shr:
case Instruction::LShr:
case Instruction::AShr:
return 1;
default:
return 0; // Cannot fold
@ -5952,7 +5922,8 @@ static Constant *GetSelectFoldableConstant(Instruction *I) {
case Instruction::Xor:
return Constant::getNullValue(I->getType());
case Instruction::Shl:
case Instruction::Shr:
case Instruction::LShr:
case Instruction::AShr:
return Constant::getNullValue(Type::UByteTy);
case Instruction::And:
return ConstantInt::getAllOnesValue(I->getType());
@ -6125,7 +6096,7 @@ Instruction *InstCombiner::visitSelectInst(SelectInst &SI) {
// this by inserting a new SRA.
unsigned Bits = X->getType()->getPrimitiveSizeInBits();
Constant *ShAmt = ConstantInt::get(Type::UByteTy, Bits-1);
Instruction *SRA = new ShiftInst(Instruction::Shr, X,
Instruction *SRA = new ShiftInst(Instruction::AShr, X,
ShAmt, "ones");
InsertNewInstBefore(SRA, SI);

View File

@ -617,10 +617,11 @@ void SROA::ConvertUsesToScalar(Value *Ptr, AllocaInst *NewAI, unsigned Offset) {
} else {
if (Offset) {
assert(NV->getType()->isInteger() && "Unknown promotion!");
if (Offset < TD.getTypeSize(NV->getType())*8)
NV = new ShiftInst(Instruction::Shr, NV,
ConstantInt::get(Type::UByteTy, Offset),
if (Offset < TD.getTypeSize(NV->getType())*8) {
NV = new ShiftInst(Instruction::LShr, NV,
ConstantInt::get(Type::UByteTy, Offset),
LI->getName(), LI);
}
} else {
assert((NV->getType()->isInteger() ||
isa<PointerType>(NV->getType())) && "Unknown promotion!");

View File

@ -120,7 +120,8 @@ Constant *llvm::ConstantFoldInstOperands(unsigned Opc, const Type *DestTy,
}
return 0;
case Instruction::Shl:
case Instruction::Shr:
case Instruction::LShr:
case Instruction::AShr:
return ConstantExpr::get(Opc, Ops[0], Ops[1]);
case Instruction::Cast:
return ConstantExpr::getCast(Ops[0], DestTy);

View File

@ -368,7 +368,8 @@ static bool DominatesMergePoint(Value *V, BasicBlock *BB,
case Instruction::Or:
case Instruction::Xor:
case Instruction::Shl:
case Instruction::Shr:
case Instruction::LShr:
case Instruction::AShr:
case Instruction::SetEQ:
case Instruction::SetNE:
case Instruction::SetLT:

View File

@ -50,7 +50,8 @@ namespace {
virtual Constant *op_or (const Constant *V1, const Constant *V2) const = 0;
virtual Constant *op_xor(const Constant *V1, const Constant *V2) const = 0;
virtual Constant *shl(const Constant *V1, const Constant *V2) const = 0;
virtual Constant *shr(const Constant *V1, const Constant *V2) const = 0;
virtual Constant *lshr(const Constant *V1, const Constant *V2) const = 0;
virtual Constant *ashr(const Constant *V1, const Constant *V2) const = 0;
virtual Constant *lessthan(const Constant *V1, const Constant *V2) const =0;
virtual Constant *equalto(const Constant *V1, const Constant *V2) const = 0;
@ -140,8 +141,11 @@ class VISIBILITY_HIDDEN TemplateRules : public ConstRules {
virtual Constant *shl(const Constant *V1, const Constant *V2) const {
return SubClassName::Shl((const ArgType *)V1, (const ArgType *)V2);
}
virtual Constant *shr(const Constant *V1, const Constant *V2) const {
return SubClassName::Shr((const ArgType *)V1, (const ArgType *)V2);
virtual Constant *lshr(const Constant *V1, const Constant *V2) const {
return SubClassName::LShr((const ArgType *)V1, (const ArgType *)V2);
}
virtual Constant *ashr(const Constant *V1, const Constant *V2) const {
return SubClassName::AShr((const ArgType *)V1, (const ArgType *)V2);
}
virtual Constant *lessthan(const Constant *V1, const Constant *V2) const {
@ -207,7 +211,8 @@ class VISIBILITY_HIDDEN TemplateRules : public ConstRules {
static Constant *Or (const ArgType *V1, const ArgType *V2) { return 0; }
static Constant *Xor (const ArgType *V1, const ArgType *V2) { return 0; }
static Constant *Shl (const ArgType *V1, const ArgType *V2) { return 0; }
static Constant *Shr (const ArgType *V1, const ArgType *V2) { return 0; }
static Constant *LShr(const ArgType *V1, const ArgType *V2) { return 0; }
static Constant *AShr(const ArgType *V1, const ArgType *V2) { return 0; }
static Constant *LessThan(const ArgType *V1, const ArgType *V2) {
return 0;
}
@ -420,12 +425,6 @@ struct VISIBILITY_HIDDEN ConstantPackedRules
static Constant *Xor(const ConstantPacked *V1, const ConstantPacked *V2) {
return EvalVectorOp(V1, V2, ConstantExpr::getXor);
}
static Constant *Shl(const ConstantPacked *V1, const ConstantPacked *V2) {
return EvalVectorOp(V1, V2, ConstantExpr::getShl);
}
static Constant *Shr(const ConstantPacked *V1, const ConstantPacked *V2) {
return EvalVectorOp(V1, V2, ConstantExpr::getShr);
}
static Constant *LessThan(const ConstantPacked *V1, const ConstantPacked *V2){
return 0;
}
@ -581,9 +580,13 @@ struct VISIBILITY_HIDDEN DirectIntRules
return ConstantInt::get(*Ty, R);
}
static Constant *Shr(const ConstantInt *V1, const ConstantInt *V2) {
BuiltinType R =
(BuiltinType)V1->getZExtValue() >> (BuiltinType)V2->getZExtValue();
static Constant *LShr(const ConstantInt *V1, const ConstantInt *V2) {
BuiltinType R = BuiltinType(V1->getZExtValue() >> V2->getZExtValue());
return ConstantInt::get(*Ty, R);
}
static Constant *AShr(const ConstantInt *V1, const ConstantInt *V2) {
BuiltinType R = BuiltinType(V1->getSExtValue() >> V2->getZExtValue());
return ConstantInt::get(*Ty, R);
}
};
@ -1278,7 +1281,8 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
case Instruction::Or: C = ConstRules::get(V1, V2).op_or (V1, V2); break;
case Instruction::Xor: C = ConstRules::get(V1, V2).op_xor(V1, V2); break;
case Instruction::Shl: C = ConstRules::get(V1, V2).shl(V1, V2); break;
case Instruction::Shr: C = ConstRules::get(V1, V2).shr(V1, V2); break;
case Instruction::LShr: C = ConstRules::get(V1, V2).lshr(V1, V2); break;
case Instruction::AShr: C = ConstRules::get(V1, V2).ashr(V1, V2); break;
case Instruction::SetEQ: C = ConstRules::get(V1, V2).equalto(V1, V2); break;
case Instruction::SetLT: C = ConstRules::get(V1, V2).lessthan(V1, V2);break;
case Instruction::SetGT: C = ConstRules::get(V1, V2).lessthan(V2, V1);break;
@ -1366,21 +1370,20 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
return const_cast<Constant*>(V2); // X / undef -> undef
case Instruction::Or: // X | undef -> -1
return ConstantInt::getAllOnesValue(V1->getType());
case Instruction::Shr:
if (!isa<UndefValue>(V2)) {
if (V1->getType()->isSigned())
return const_cast<Constant*>(V1); // undef >>s X -> undef
// undef >>u X -> 0
} else if (isa<UndefValue>(V1)) {
return const_cast<Constant*>(V1); // undef >> undef -> undef
} else {
if (V1->getType()->isSigned())
return const_cast<Constant*>(V1); // X >>s undef -> X
}
return Constant::getNullValue(V1->getType());// X >>u undef -> 0
case Instruction::LShr:
if (isa<UndefValue>(V2) && isa<UndefValue>(V1))
return const_cast<Constant*>(V1); // undef lshr undef -> undef
return Constant::getNullValue(V1->getType()); // X lshr undef -> 0
// undef lshr X -> 0
case Instruction::AShr:
if (!isa<UndefValue>(V2))
return const_cast<Constant*>(V1); // undef ashr X --> undef
else if (isa<UndefValue>(V1))
return const_cast<Constant*>(V1); // undef ashr undef -> undef
else
return const_cast<Constant*>(V1); // X ashr undef --> X
case Instruction::Shl:
// undef << X -> 0 X << undef -> 0
// undef << X -> 0 or X << undef -> 0
return Constant::getNullValue(V1->getType());
}
}
@ -1466,7 +1469,8 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
return ConstantFoldBinaryInstruction(Opcode, V2, V1);
case Instruction::Shl:
case Instruction::Shr:
case Instruction::LShr:
case Instruction::AShr:
case Instruction::Sub:
case Instruction::SDiv:
case Instruction::UDiv:

View File

@ -498,20 +498,11 @@ Constant *ConstantExpr::getSetGE(Constant *C1, Constant *C2) {
Constant *ConstantExpr::getShl(Constant *C1, Constant *C2) {
return get(Instruction::Shl, C1, C2);
}
Constant *ConstantExpr::getShr(Constant *C1, Constant *C2) {
return get(Instruction::Shr, C1, C2);
Constant *ConstantExpr::getLShr(Constant *C1, Constant *C2) {
return get(Instruction::LShr, C1, C2);
}
Constant *ConstantExpr::getUShr(Constant *C1, Constant *C2) {
if (C1->getType()->isUnsigned()) return getShr(C1, C2);
return getCast(getShr(getCast(C1,
C1->getType()->getUnsignedVersion()), C2), C1->getType());
}
Constant *ConstantExpr::getSShr(Constant *C1, Constant *C2) {
if (C1->getType()->isSigned()) return getShr(C1, C2);
return getCast(getShr(getCast(C1,
C1->getType()->getSignedVersion()), C2), C1->getType());
Constant *ConstantExpr::getAShr(Constant *C1, Constant *C2) {
return get(Instruction::AShr, C1, C2);
}
/// getWithOperandReplaced - Return a constant expression identical to this
@ -1330,7 +1321,9 @@ namespace llvm {
return new UnaryConstantExpr(Instruction::Cast, V.second[0], Ty);
if ((V.first >= Instruction::BinaryOpsBegin &&
V.first < Instruction::BinaryOpsEnd) ||
V.first == Instruction::Shl || V.first == Instruction::Shr)
V.first == Instruction::Shl ||
V.first == Instruction::LShr ||
V.first == Instruction::AShr)
return new BinaryConstantExpr(V.first, V.second[0], V.second[1]);
if (V.first == Instruction::Select)
return new SelectConstantExpr(V.second[0], V.second[1], V.second[2]);
@ -1364,7 +1357,8 @@ namespace llvm {
OldC->getOperand(2));
break;
case Instruction::Shl:
case Instruction::Shr:
case Instruction::LShr:
case Instruction::AShr:
New = ConstantExpr::getShiftTy(NewTy, OldC->getOpcode(),
OldC->getOperand(0), OldC->getOperand(1));
break;
@ -1453,7 +1447,8 @@ Constant *ConstantExpr::getPtrPtrFromArrayPtr(Constant *C) {
Constant *ConstantExpr::getTy(const Type *ReqTy, unsigned Opcode,
Constant *C1, Constant *C2) {
if (Opcode == Instruction::Shl || Opcode == Instruction::Shr)
if (Opcode == Instruction::Shl || Opcode == Instruction::LShr ||
Opcode == Instruction::AShr)
return getShiftTy(ReqTy, Opcode, C1, C2);
// Check the operands for consistency first
assert(Opcode >= Instruction::BinaryOpsBegin &&
@ -1521,9 +1516,10 @@ Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2) {
assert(C1->getType() == C2->getType() && "Op types should be identical!");
break;
case Instruction::Shl:
case Instruction::Shr:
case Instruction::LShr:
case Instruction::AShr:
assert(C2->getType() == Type::UByteTy && "Shift should be by ubyte!");
assert((C1->getType()->isInteger() || isa<PackedType>(C1->getType())) &&
assert(C1->getType()->isInteger() &&
"Tried to create a shift operation on a non-integer type!");
break;
default:
@ -1558,8 +1554,9 @@ Constant *ConstantExpr::getSelectTy(const Type *ReqTy, Constant *C,
Constant *ConstantExpr::getShiftTy(const Type *ReqTy, unsigned Opcode,
Constant *C1, Constant *C2) {
// Check the operands for consistency first
assert((Opcode == Instruction::Shl ||
Opcode == Instruction::Shr) &&
assert((Opcode == Instruction::Shl ||
Opcode == Instruction::LShr ||
Opcode == Instruction::AShr) &&
"Invalid opcode in binary constant expression");
assert(C1->getType()->isIntegral() && C2->getType() == Type::UByteTy &&
"Invalid operand types for Shift constant expr!");

View File

@ -128,7 +128,8 @@ const char *Instruction::getOpcodeName(unsigned OpCode) {
case Select: return "select";
case Call: return "call";
case Shl: return "shl";
case Shr: return "shr";
case LShr: return "lshr";
case AShr: return "ashr";
case VAArg: return "va_arg";
case ExtractElement: return "extractelement";
case InsertElement: return "insertelement";

View File

@ -1222,17 +1222,6 @@ bool BinaryOperator::swapOperands() {
return false;
}
//===----------------------------------------------------------------------===//
// ShiftInst Class
//===----------------------------------------------------------------------===//
/// isLogicalShift - Return true if this is a logical shift left or a logical
/// shift right.
bool ShiftInst::isLogicalShift() const {
return getOpcode() == Instruction::Shl || getType()->isUnsigned();
}
//===----------------------------------------------------------------------===//
// CastInst Class
//===----------------------------------------------------------------------===//

View File

@ -1257,7 +1257,7 @@ StackerCompiler::handle_word( int tkn )
LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
CastInst* castop = new CastInst( op1, Type::UByteTy );
bb->getInstList().push_back( castop );
ShiftInst* shrop = new ShiftInst( Instruction::Shr, op2, castop );
ShiftInst* shrop = new ShiftInst( Instruction::AShr, op2, castop );
bb->getInstList().push_back( shrop );
push_value( bb, shrop );
break;

View File

@ -1,5 +1,5 @@
; RUN: llvm-as < %s | opt -instcombine -disable-output &&
; RUN: llvm-as < %s | opt -instcombine | llvm-dis | not grep 'shr int'
; RUN: llvm-as < %s | opt -instcombine | llvm-dis | grep 'lshr int'
int %test0(int %X, ubyte %A) {
%Y = shr int %X, ubyte %A ; can be logical shift.

View File

@ -788,7 +788,8 @@ void CppWriter::printConstant(const Constant *CV) {
case Instruction::SetLT: Out << "getSetLT"; break;
case Instruction::SetGT: Out << "getSetGT"; break;
case Instruction::Shl: Out << "getShl"; break;
case Instruction::Shr: Out << "getShr"; break;
case Instruction::LShr: Out << "getLShr"; break;
case Instruction::AShr: Out << "getAShr"; break;
case Instruction::Select: Out << "getSelect"; break;
case Instruction::ExtractElement: Out << "getExtractElement"; break;
case Instruction::InsertElement: Out << "getInsertElement"; break;
@ -1034,7 +1035,8 @@ CppWriter::printInstruction(const Instruction *I, const std::string& bbname) {
case Instruction::Or:
case Instruction::Xor:
case Instruction::Shl:
case Instruction::Shr:{
case Instruction::LShr:
case Instruction::AShr:{
Out << "BinaryOperator* " << iName << " = BinaryOperator::create(";
switch (I->getOpcode()) {
case Instruction::Add: Out << "Instruction::Add"; break;
@ -1050,7 +1052,8 @@ CppWriter::printInstruction(const Instruction *I, const std::string& bbname) {
case Instruction::Or: Out << "Instruction::Or"; break;
case Instruction::Xor: Out << "Instruction::Xor"; break;
case Instruction::Shl: Out << "Instruction::Shl"; break;
case Instruction::Shr: Out << "Instruction::Shr"; break;
case Instruction::LShr:Out << "Instruction::LShr"; break;
case Instruction::AShr:Out << "Instruction::AShr"; break;
default: Out << "Instruction::BadOpCode"; break;
}
Out << ", " << opNames[0] << ", " << opNames[1] << ", \"";